From b80f431964761b13b3c9a1c74ba175b1ee91a1a8 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 01/31] Migrate Structure --- .../modules/ROOT/assets/images/AWS-deploy.png | Bin 0 -> 602969 bytes docs/modules/ROOT/assets/images/remove.txt | 1 + .../ROOT/assets/images/scf-azure-adapter.svg | 272 ++++++++++++++++++ .../ROOT/pages}/README.adoc | 0 .../ROOT/pages}/_intro.adoc | 0 .../ROOT/pages}/adapters/aws-intro.adoc | 0 .../ROOT/pages}/adapters/aws.adoc | 0 .../ROOT/pages}/adapters/azure-intro.adoc | 0 .../ROOT/pages}/adapters/azure.adoc | 0 .../ROOT/pages}/adapters/gcp-intro.adoc | 0 .../ROOT/pages}/adapters/gcp.adoc | 0 .../ROOT/pages}/functional.adoc | 0 .../ROOT/pages}/getting-started.adoc | 0 .../ROOT/pages}/index.adoc | 0 .../ROOT/pages}/sagan-index.adoc | 0 .../ROOT/pages}/spring-cloud-function.adoc | 0 .../ROOT/pages}/spring-integration.adoc | 0 17 files changed, 273 insertions(+) create mode 100644 docs/modules/ROOT/assets/images/AWS-deploy.png create mode 100644 docs/modules/ROOT/assets/images/remove.txt create mode 100644 docs/modules/ROOT/assets/images/scf-azure-adapter.svg rename docs/{src/main/asciidoc => modules/ROOT/pages}/README.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/_intro.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/aws-intro.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/aws.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/azure-intro.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/azure.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/gcp-intro.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/adapters/gcp.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/functional.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/getting-started.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/index.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/sagan-index.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/spring-cloud-function.adoc (100%) rename docs/{src/main/asciidoc => modules/ROOT/pages}/spring-integration.adoc (100%) diff --git a/docs/modules/ROOT/assets/images/AWS-deploy.png b/docs/modules/ROOT/assets/images/AWS-deploy.png new file mode 100644 index 0000000000000000000000000000000000000000..c840e1396736e81c706e1bcac783b2bee781b6db GIT binary patch literal 602969 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­MgUgQui)8rD4Z+Kfab65N>#l9mCteq3SFI_D*| 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

5voOCh=mB8RUQqe$O5`Xagy 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

xc*jnzqrSq&oreJHD}7 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μ)>GVqz$~d4<1cx5{+|Y;F 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

h?H6~nCIjMT#tHa0QI8Hk(0VxeUH_c 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

96$Z%RXS-skP;6 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

qf9;R_CtL3AY| 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�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�Tp0By^B5RIy)6}9z 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 DwtSbC literal 0 HcmV?d00001 diff --git a/docs/modules/ROOT/assets/images/remove.txt b/docs/modules/ROOT/assets/images/remove.txt new file mode 100644 index 000000000..bbd40769d --- /dev/null +++ b/docs/modules/ROOT/assets/images/remove.txt @@ -0,0 +1 @@ +please remove once this directory is not empty \ No newline at end of file diff --git a/docs/modules/ROOT/assets/images/scf-azure-adapter.svg b/docs/modules/ROOT/assets/images/scf-azure-adapter.svg new file mode 100644 index 000000000..8a064d8f4 --- /dev/null +++ b/docs/modules/ROOT/assets/images/scf-azure-adapter.svg @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/main/asciidoc/README.adoc b/docs/modules/ROOT/pages/README.adoc similarity index 100% rename from docs/src/main/asciidoc/README.adoc rename to docs/modules/ROOT/pages/README.adoc diff --git a/docs/src/main/asciidoc/_intro.adoc b/docs/modules/ROOT/pages/_intro.adoc similarity index 100% rename from docs/src/main/asciidoc/_intro.adoc rename to docs/modules/ROOT/pages/_intro.adoc diff --git a/docs/src/main/asciidoc/adapters/aws-intro.adoc b/docs/modules/ROOT/pages/adapters/aws-intro.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/aws-intro.adoc rename to docs/modules/ROOT/pages/adapters/aws-intro.adoc diff --git a/docs/src/main/asciidoc/adapters/aws.adoc b/docs/modules/ROOT/pages/adapters/aws.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/aws.adoc rename to docs/modules/ROOT/pages/adapters/aws.adoc diff --git a/docs/src/main/asciidoc/adapters/azure-intro.adoc b/docs/modules/ROOT/pages/adapters/azure-intro.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/azure-intro.adoc rename to docs/modules/ROOT/pages/adapters/azure-intro.adoc diff --git a/docs/src/main/asciidoc/adapters/azure.adoc b/docs/modules/ROOT/pages/adapters/azure.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/azure.adoc rename to docs/modules/ROOT/pages/adapters/azure.adoc diff --git a/docs/src/main/asciidoc/adapters/gcp-intro.adoc b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/gcp-intro.adoc rename to docs/modules/ROOT/pages/adapters/gcp-intro.adoc diff --git a/docs/src/main/asciidoc/adapters/gcp.adoc b/docs/modules/ROOT/pages/adapters/gcp.adoc similarity index 100% rename from docs/src/main/asciidoc/adapters/gcp.adoc rename to docs/modules/ROOT/pages/adapters/gcp.adoc diff --git a/docs/src/main/asciidoc/functional.adoc b/docs/modules/ROOT/pages/functional.adoc similarity index 100% rename from docs/src/main/asciidoc/functional.adoc rename to docs/modules/ROOT/pages/functional.adoc diff --git a/docs/src/main/asciidoc/getting-started.adoc b/docs/modules/ROOT/pages/getting-started.adoc similarity index 100% rename from docs/src/main/asciidoc/getting-started.adoc rename to docs/modules/ROOT/pages/getting-started.adoc diff --git a/docs/src/main/asciidoc/index.adoc b/docs/modules/ROOT/pages/index.adoc similarity index 100% rename from docs/src/main/asciidoc/index.adoc rename to docs/modules/ROOT/pages/index.adoc diff --git a/docs/src/main/asciidoc/sagan-index.adoc b/docs/modules/ROOT/pages/sagan-index.adoc similarity index 100% rename from docs/src/main/asciidoc/sagan-index.adoc rename to docs/modules/ROOT/pages/sagan-index.adoc diff --git a/docs/src/main/asciidoc/spring-cloud-function.adoc b/docs/modules/ROOT/pages/spring-cloud-function.adoc similarity index 100% rename from docs/src/main/asciidoc/spring-cloud-function.adoc rename to docs/modules/ROOT/pages/spring-cloud-function.adoc diff --git a/docs/src/main/asciidoc/spring-integration.adoc b/docs/modules/ROOT/pages/spring-integration.adoc similarity index 100% rename from docs/src/main/asciidoc/spring-integration.adoc rename to docs/modules/ROOT/pages/spring-integration.adoc From 29708de88fbf95fca54ece03cbdb8555364e15b6 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 02/31] Insert explicit ids for headers --- docs/modules/ROOT/pages/README.adoc | 4 ++ .../ROOT/pages/adapters/aws-intro.adoc | 12 ++++++ docs/modules/ROOT/pages/adapters/aws.adoc | 6 +++ .../ROOT/pages/adapters/azure-intro.adoc | 17 +++++++- .../ROOT/pages/adapters/gcp-intro.adoc | 9 ++++ docs/modules/ROOT/pages/functional.adoc | 5 +++ docs/modules/ROOT/pages/index.adoc | 1 + .../ROOT/pages/spring-cloud-function.adoc | 41 +++++++++++++++++++ 8 files changed, 94 insertions(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc index 6d0f4cf8d..3e3adfa2e 100644 --- a/docs/modules/ROOT/pages/README.adoc +++ b/docs/modules/ROOT/pages/README.adoc @@ -2,18 +2,22 @@ image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={branch}[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] +[[introduction]] == Introduction include::_intro.adoc[] +[[getting-started]] == Getting Started include::getting-started.adoc[] +[[building]] == Building include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[] +[[contributing]] == Contributing include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] diff --git a/docs/modules/ROOT/pages/adapters/aws-intro.adoc b/docs/modules/ROOT/pages/adapters/aws-intro.adoc index 8bd82bb2f..14a3d7de9 100644 --- a/docs/modules/ROOT/pages/adapters/aws-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/aws-intro.adoc @@ -1,5 +1,6 @@ :branch: master +[[aws-lambda]] === AWS Lambda The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. @@ -7,6 +8,7 @@ The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and c The details of how to get stared with AWS Lambda is out of scope of this document, so the expectation is that user has some familiarity with AWS and AWS Lambda and wants to learn what additional value spring provides. +[[getting-started]] ==== Getting Started One of the goals of Spring Cloud Function framework is to provide necessary infrastructure elements to enable a _simple function application_ @@ -56,6 +58,7 @@ isolating you from the specifics of AWS Lambda API, for some cases you may want to use. The next section will explain you how you can accomplish just that. +[[aws-request-handlers]] ==== AWS Request Handlers The adapter has a couple of generic request handlers that you can use. The most generic is (and the one we used in the Getting Started section) @@ -69,6 +72,7 @@ property or environment variable. The functions are extracted from the Spring Cl the framework will attempt to find a default following the search order where it searches first for `Function` then `Consumer` and finally `Supplier`). +[[aws-function-routing]] ==== AWS Function Routing One of the core features of Spring Cloud Function is https://docs.spring.io/spring-cloud-function/docs/{project-version}/reference/html/spring-cloud-function.html#_function_routing_and_filtering[routing] @@ -90,10 +94,12 @@ Also, note that since AWS does not allow dots `.` and/or hyphens`-` in the name dots with underscores and hyphens with camel case. So for example `spring.cloud.function.definition` becomes `spring_cloud_function_definition` and `spring.cloud.function.routing-expression` becomes `spring_cloud_function_routingExpression`. +[[aws-function-routing-with-custom-runtime]] ===== AWS Function Routing with Custom Runtime When using <> Function Routing works the same way. All you need is to specify `functionRouter` as AWS Handler the same way you would use the name of the function as handler. +[[notes-on-jar-layout]] ==== Notes on JAR Layout You don't need the Spring Cloud Function Web or Stream adapter at runtime in Lambda, so you might @@ -158,12 +164,14 @@ then additional transformers must be configured as part of the maven-shade-plugi ---- +[[build-file-setup]] ==== Build file setup In order to run Spring Cloud Function applications on AWS Lambda, you can leverage Maven or Gradle plugins offered by the cloud platform provider. +[[maven]] ===== Maven In order to use the adapter plugin for Maven, add the plugin dependency to your `pom.xml` @@ -202,6 +210,7 @@ You can use the Spring Boot Maven Plugin to generate the <>. You can find the entire sample `pom.xml` file for deploying Spring Cloud Function applications to AWS Lambda with Maven https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/pom.xml[here]. +[[gradle]] ===== Gradle In order to use the adapter plugin for Gradle, add the dependency to your `build.gradle` file: @@ -270,6 +279,7 @@ assemble.dependsOn = [thinJar] You can find the entire sample `build.gradle` file for deploying Spring Cloud Function applications to AWS Lambda with Gradle https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/build.gradle[here]. +[[upload]] ==== Upload Build the sample under `spring-cloud-function-samples/function-sample-aws` and upload the `-aws` jar file to Lambda. The handler can be `example.Handler` or `org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler` (FQN of the class, _not_ a method reference, although Lambda does accept method references). @@ -295,6 +305,7 @@ The input type for the function in the AWS sample is a Foo with a single propert NOTE: The AWS sample app is written in the "functional" style (as an `ApplicationContextInitializer`). This is much faster on startup in Lambda than the traditional `@Bean` style, so if you don't need `@Beans` (or `@EnableAutoConfiguration`) it's a good choice. Warm starts are not affected. +[[type-conversion]] ==== Type Conversion Spring Cloud Function will attempt to transparently handle type conversion between the raw @@ -306,6 +317,7 @@ incoming stream event to an instance of `Foo`. In the event type is not known or can not be determined (e.g., `Function`) we will attempt to convert an incoming stream event to a generic `Map`. +[[raw-input]] ====== Raw Input There are times when you may want to have access to a raw input. In this case all you need is to declare your diff --git a/docs/modules/ROOT/pages/adapters/aws.adoc b/docs/modules/ROOT/pages/adapters/aws.adoc index 0912ded38..31b25b7b3 100644 --- a/docs/modules/ROOT/pages/adapters/aws.adoc +++ b/docs/modules/ROOT/pages/adapters/aws.adoc @@ -3,10 +3,12 @@ The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. +[[introduction]] == Introduction include::adapters/aws-intro.adoc[] +[[functional-bean-definitions]] == Functional Bean Definitions Your functions will start much quicker if you can use functional bean definitions instead of `@Bean`. To do this make your main class @@ -37,6 +39,7 @@ public class FuncApplication implements ApplicationContextInitializer` as an input parameter to your function and then access `aws-context` from message headers. For convenience we provide AWSLambdaUtils.AWS_CONTEXT constant. +[[platform-specific-features]] == Platform Specific Features +[[http-and-api-gateway]] === HTTP and API Gateway AWS has some platform-specific data types, including batching of messages, which is much more efficient than processing each one individually. To make use of these types you can write a function that depends on those types. Or you can rely on Spring to extract the data from the AWS types and convert it to a Spring `Message`. To do this you tell AWS that the function is of a specific generic handler type (depending on the AWS service) and provide a bean of type `Function,Message>`, where `S` and `T` are your business data types. If there is more than one bean of type `Function` you may also need to configure the Spring Boot property `function.name` to be the name of the target bean (e.g. use `FUNCTION_NAME` as an environment variable). @@ -62,6 +67,7 @@ The supported AWS services and generic handler types are listed below: For example, to deploy behind an API Gateway, use `--handler org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler` in your AWS command line (in via the UI) and define a `@Bean` of type `Function,Message>` where `Foo` and `Bar` are POJO types (the data will be marshalled and unmarshalled by AWS using Jackson). +[[custom-runtime]] == Custom Runtime You can also benefit from https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html[AWS Lambda custom runtime] feature of AWS Lambda diff --git a/docs/modules/ROOT/pages/adapters/azure-intro.adoc b/docs/modules/ROOT/pages/adapters/azure-intro.adoc index 59ceca215..f5e58c5a8 100644 --- a/docs/modules/ROOT/pages/adapters/azure-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/azure-intro.adoc @@ -1,5 +1,6 @@ :branch: master +[[microsoft-azure-functions]] == Microsoft Azure Functions :sectnums: @@ -19,10 +20,12 @@ With the Azure Web Adapter you can deploy any Spring Web application as an Azure This adapter hides the Azure annotations complexity and uses the familiar https://docs.spring.io/spring-boot/docs/current/reference/html/web.html[Spring Web] programming model instead. For further information follow the <> section below. +[[azure-adapter]] == Azure Adapter Provides `Spring` & `Spring Cloud Function` integration for Azure Functions. +[[dependencies]] === Dependencies In order to enable the Azure Function integration add the azure adapter dependency to your `pom.xml` or `build.gradle` @@ -127,6 +130,7 @@ public class HttpTriggerDemoApplication { <1> The `@SpringBootApplication` annotated class is used as a `Main-Class` as explained in <>. <2> Functions auto-wired and used in the Azure function handlers. +[[function-catalog]] ==== Function Catalog The Spring Cloud Function supports a range of type signatures for user-defined functions, while providing a consistent execution model. @@ -137,6 +141,7 @@ But those are treated as plain Java class instances, not as a canonical Spring C To leverage Spring Cloud Function and have access to the canonical function representations, you need to auto-wire the `FunctionCatalog` and use it in your handler, like the `functionCatalog` instance the `springCloudFunction()` handler above. +[[accessing-azure-executioncontext]] ==== Accessing Azure ExecutionContext Some time there is a need to access the target execution context provided by the Azure runtime in the form of `com.microsoft.azure.functions.ExecutionContext`. @@ -186,6 +191,7 @@ Usually the Azure Maven (or Gradle) plugins are used to generate the necessary c IMPORTANT: The Azure https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#folder-structure[packaging format] is not compatible with the default Spring Boot packaging (e.g. `uber jar`). The <> section below explains how to handle this. +[[azure-maven/gradle-plugins]] ==== Azure Maven/Gradle Plugins Azure provides https://github.com/microsoft/azure-maven-plugins/tree/develop/azure-functions-maven-plugin[Maven] and https://github.com/microsoft/azure-gradle-plugins/tree/master/azure-functions-gradle-plugin[Gradle] plugins to process the annotated classes, generate the necessary configurations and produce the expected package layout. @@ -327,6 +333,7 @@ For local runs, add the `MAIN_CLASS` variable to your `local.settings.json` file IMPORTANT: If the `MAIN_CLASS` variable is not set, the Azure adapter lookups the `MANIFEST/META-INFO` attributes from the jars found on the classpath and selects the first `Main-Class:` annotated with either a `@SpringBootApplication` or `@SpringBootConfiguration` annotation. +[[metadata-configuration]] ==== Metadata Configuration You can use a shared https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json[host.json] file to configure the function app. @@ -346,6 +353,7 @@ The host.json metadata file contains configuration options that affect all funct TIP: If the file is not in the project top folder you need to configure your plugins accordingly (like `hostJson` maven attribute). +[[samples]] === Samples Here is a list of various Spring Cloud Function Azure Adapter samples you can explore: @@ -389,6 +397,7 @@ dependencies { The same <> and <> instructions apply to the `Azure Web Adapter` as well. +[[samples]] === Samples For further information, explore the following, Azure Web Adapter, sample: @@ -400,6 +409,7 @@ For further information, explore the following, Azure Web Adapter, sample: Common instructions for building and deploying both, `Azure Adapter` and `Azure Web Adapter` type of applications. +[[build]] === Build ==== @@ -416,6 +426,7 @@ Common instructions for building and deploying both, `Azure Adapter` and `Azure ---- ==== +[[running-locally]] === Running locally To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here]). @@ -437,6 +448,7 @@ Then run the sample: ---- ==== +[[running-on-azure]] === Running on Azure Make sure you are logged in your Azure account. @@ -461,6 +473,7 @@ and deploy ---- ==== +[[debug-locally]] === Debug locally Run the function in debug mode. @@ -516,12 +529,14 @@ Here is snippet for a `VSCode` remote debugging configuration: } ---- +[[functioninvoker-deprecated]] == FunctionInvoker (deprecated) WARNING: The legacy `FunctionInvoker` programming model is deprecated and will not be supported going forward. For additional documentation and samples about the Function Integration approach follow the https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure/[azure-sample] README and code. +[[relevant-links]] == Relevant Links - https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/getting-started-with-spring-cloud-function-in-azure[Spring Cloud Function in Azure] @@ -530,4 +545,4 @@ For additional documentation and samples about the Function Integration approach - https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption[Azure Functions Java developer guide] - https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference?tabs=blob[Azure Functions developer guide] -:sectnums!: \ No newline at end of file +:sectnums!: diff --git a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc index 1f72b19ed..4826d6d58 100644 --- a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc @@ -1,10 +1,12 @@ :branch: master +[[google-cloud-functions]] === Google Cloud Functions The Google Cloud Functions adapter enables Spring Cloud Function apps to run on the https://cloud.google.com/functions[Google Cloud Functions] serverless platform. You can either run the function locally using the open source https://github.com/GoogleCloudPlatform/functions-framework-java[Google Functions Framework for Java] or on GCP. +[[project-dependencies]] ==== Project Dependencies Start by adding the `spring-cloud-function-adapter-gcp` dependency to your project. @@ -62,10 +64,12 @@ NOTE: The function target should always be set to `org.springframework.cloud.fun A full example of a working `pom.xml` can be found in the https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-gcp-http/pom.xml[Spring Cloud Functions GCP sample]. +[[http-functions]] ==== HTTP Functions Google Cloud Functions supports deploying https://cloud.google.com/functions/docs/writing/http[HTTP Functions], which are functions that are invoked by HTTP request. The sections below describe instructions for deploying a Spring Cloud Function as an HTTP Function. +[[getting-started]] ===== Getting Started Let’s start with a simple Spring Cloud Function example: @@ -106,6 +110,7 @@ Invoke the HTTP function: curl http://localhost:8080/ -d "hello" ---- +[[deploy-to-gcp]] ===== Deploy to GCP Start by packaging your application. @@ -158,6 +163,7 @@ public Function> function() { +[[background-functions]] ==== Background Functions Google Cloud Functions also supports deploying https://cloud.google.com/functions/docs/writing/background[Background Functions] which are invoked indirectly in response to an event, such as a message on a https://cloud.google.com/pubsub[Cloud Pub/Sub] topic, a change in a https://cloud.google.com/storage[Cloud Storage] bucket, or a https://firebase.google.com/[Firebase] event. @@ -167,6 +173,7 @@ The `spring-cloud-function-adapter-gcp` allows for functions to be deployed as b The sections below describe the process for writing a Cloud Pub/Sub topic background function. However, there are a number of different event types that can trigger a background function to execute which are not discussed here; these are described in the https://cloud.google.com/functions/docs/calling[Background Function triggers documentation]. +[[getting-started]] ===== Getting Started Let’s start with a simple Spring Cloud Function which will run as a GCF background function: @@ -259,6 +266,7 @@ curl localhost:8080 -H "Content-Type: application/json" -d '{"data":"hello"}' Verify that the function was invoked by viewing the logs. +[[deploy-to-gcp]] ===== Deploy to GCP In order to deploy your background function to GCP, first package your application. @@ -287,6 +295,7 @@ Google Cloud Function will now invoke the function every time a message is publi For a walkthrough on testing and verifying your background function, see the instructions for running the https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-background/[GCF Background Function sample]. +[[sample-functions]] ==== Sample Functions The project provides the following sample functions as reference: diff --git a/docs/modules/ROOT/pages/functional.adoc b/docs/modules/ROOT/pages/functional.adoc index a12f520ac..7e4e89736 100644 --- a/docs/modules/ROOT/pages/functional.adoc +++ b/docs/modules/ROOT/pages/functional.adoc @@ -1,5 +1,6 @@ Spring Cloud Function supports a "functional" style of bean declarations for small apps where you need fast startup. The functional style of bean declaration was a feature of Spring Framework 5.0 with significant enhancements in 5.1. +[[comparing-functional-with-traditional-bean-definitions]] == Comparing Functional with Traditional Bean Definitions Here's a vanilla Spring Cloud Function application from with the @@ -113,6 +114,7 @@ public void initialize(GenericApplicationContext context) { } ---- +[[limitations-of-functional-bean-declaration]] == Limitations of Functional Bean Declaration Most Spring Cloud Function apps have a relatively small scope compared to the whole of Spring Boot, @@ -128,6 +130,7 @@ functional mode" using `spring.functional.enabled=false` so that Spring Boot can Spring Cloud Function supports visualization of functions available in `FunctionCatalog` through Actuator endpoints as well as programmatic way. +[[programmatic-way]] ==== Programmatic way To see function available within your application context programmatically all you need is access to `FunctionCatalog`. There you can @@ -143,6 +146,7 @@ Set names = functionCatalog.getNames(null); will list the names of all t . . . ---- +[[actuator]] ==== Actuator Since actuator and web are optional, you must first add one of the web dependencies as well as add the actuator dependency manually. The following example shows how to add the dependency for the Web framework: @@ -198,6 +202,7 @@ Your output should look something like this: {"type":"SUPPLIER","output-type":"string"}. . . ---- +[[testing-functional-applications]] = Testing Functional Applications Spring Cloud Function also has some utilities for integration testing that will be very familiar to Spring Boot users. diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index ebc517b8a..cc9d0d1dd 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,3 +1,4 @@ +[[spring-cloud-function-reference-documentation]] = Spring Cloud Function Reference Documentation Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin, Chris Bono, Artem Bilan diff --git a/docs/modules/ROOT/pages/spring-cloud-function.adoc b/docs/modules/ROOT/pages/spring-cloud-function.adoc index 7eea6e5fc..9cff8a176 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function.adoc @@ -1,3 +1,4 @@ +[[spring-cloud-function]] = Spring Cloud Function Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin @@ -12,20 +13,24 @@ Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin :nofooter: :branch: master +[[introduction]] == Introduction include::_intro.adoc[] include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing-docs.adoc[] +[[getting-started]] == Getting Started include::getting-started.adoc[] +[[programming-model]] == Programming model [[function.catalog]] +[[function-catalog-and-flexible-function-signatures]] === Function Catalog and Flexible Function Signatures One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions, @@ -42,6 +47,7 @@ your function implementation. Reactive programming model also enables functional support for features that would be otherwise difficult to impossible to implement using imperative programming style. For more on this please read <> section. +[[java-8-function-support]] === Java 8 function support Spring Cloud Function embraces and builds on top of the 3 core functional interfaces defined by Java @@ -80,6 +86,7 @@ adapters as well as other frameworks using Spring Cloud Function as the core pro So in summary Spring Cloud Function instruments java functions with additional features to be utilised in variety of execution contexts. +[[function-definition]] ==== Function definition While the previous example shows you how to lookup function in FunctionCatalog programmatically, in a typical integration case where Spring Cloud Function used as programming model by another framework (e.fg. Spring Cloud Stream), you declare which functions to use via `spring.cloud.function.definition` property. Knowing that it is important to understand some default behaviour when it comes to discovering functions in `FunctionCatalog`. For example, if you only have one Functional bean in your `ApplicationContext`, the `spring.cloud.function.definition` property typically will not be required, since a single function in `FunctionCatalog` can be looked up by an empty name or any name. For example, assuming that `uppercase` is the only function in your catalog, it can be looked up as `catalog.lookup(null)`, `catalog.lookup(“”)`, `catalog.lookup(“foo”)` That said, for cases where you are using framework such as Spring Cloud Stream which uses `spring.cloud.function.definition` it is best practice and recommended to always use `spring.cloud.function.definition` property. @@ -91,6 +98,7 @@ For example, spring.cloud.function.definition=uppercase ---- +[[filtering-ineligible-functions]] ==== Filtering ineligible functions A typical Application Context may include beans that are valid java functions, but not intended to be candidates to be registered with `FunctionCatalog`. Such beans could be auto-configurations from other projects or any other beans that qualify to be Java functions. @@ -105,6 +113,7 @@ For example, spring.cloud.function.ineligible-definitions=foo,bar ---- +[[supplier]] ==== Supplier Supplier can be _reactive_ - `Supplier>` or _imperative_ - `Supplier`. From the invocation standpoint this should make no difference @@ -138,23 +147,27 @@ public Supplier> someSupplier() { } ---- +[[function]] ==== Function Function can also be written in imperative or reactive way, yet unlike Supplier and Consumer there are no special considerations for the implementor other then understanding that when used within frameworks such as https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] and others, reactive function is invoked only once to pass a reference to the stream (Flux or Mono) and imperative is invoked once per event. +[[consumer]] ==== Consumer Consumer is a little bit special because it has a `void` return type, which implies blocking, at least potentially. Most likely you will not need to write `Consumer>`, but if you do need to do that, remember to subscribe to the input flux. +[[function-composition]] === Function Composition Function Composition is a feature that allows one to compose several functions into one. The core support is based on function composition feature available with https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#andThen-java.util.function.Function-[Function.andThen(..)] support available since Java 8. However on top of it, we provide few additional features. +[[declarative-function-composition]] ==== Declarative Function Composition This feature allows you to provide composition instruction in a declarative way using `|` (pipe) or `,` (comma) delimiter @@ -169,6 +182,7 @@ function `uppercase` and function `reverse`. In fact that is one of the reasons since the definition of a function can be a composition of several named functions. And as mentioned you can use `,` instead of pipe (such as `...definition=uppercase,reverse`). +[[composing-non-functions]] ==== Composing non-Functions Spring Cloud Function also supports composing Supplier with `Consumer` or `Function` as well as `Function` with `Consumer`. What's important here is to understand the end product of such definitions. @@ -178,6 +192,7 @@ Following the same logic composing Function with Consumer will result in Consume And of course you can't compose uncomposable such as Consumer and Function, Consumer and Supplier etc. +[[function-routing-and-filtering]] === Function Routing and Filtering Since version 2.2 Spring Cloud Function provides routing feature allowing @@ -199,6 +214,7 @@ public class RoutingFunction implements Function { The routing instructions could be communicated in several ways. We support providing instructions via Message headers, System properties as well as pluggable strategy. So let's look at some of the details +[[messageroutingcallback]] ==== MessageRoutingCallback The `MessageRoutingCallback` is a strategy to assist with determining the name of the route-to function definition. @@ -299,6 +315,7 @@ public DefaultMessageRoutingHandler defaultRoutingHandler() { } ---- +[[function-filtering]] ==== Function Filtering Filtering is the type of routing where there are only two paths - 'go' or 'discard'. In terms of functions it mean you only want to invoke a certain function if some condition returns 'true', otherwise you want to discard input. @@ -329,6 +346,7 @@ due to the nature of the reactive functions which are invoked only once to pass is handled by the reactor, hence we can not access and/or rely on the routing instructions communicated via individual values (e.g., Message). +[[multiple-routers]] ==== Multiple Routers By default the framework will always have a single routing function configured as described in previous sections. However, there are times when you may need more than one routing function. @@ -381,6 +399,7 @@ public void testMultipleRouters() { } ---- +[[input/output-enrichment]] === Input/Output Enrichment There are often times when you need to modify or refine an incoming or outgoing Message and to keep your code clean of non-functional concerns. You don’t want to do it inside of your business logic. @@ -461,6 +480,7 @@ In the event you are dealing with functions that have multiple inputs (next sect --spring.cloud.function.configuration.echo.input-header-mapping-expression[1].key2='hello2' ---- +[[function-arity]] === Function Arity There are times when a stream of data needs to be categorized and organized. For example, @@ -496,6 +516,7 @@ IMPORTANT: IMPORTANT: At the moment, function arity is *only* supported for reac where evaluation and computation on confluence of events typically requires view into a stream of events rather than single event. +[[input-header-propagation]] === Input Header propagation In a typical scenario input Message headers are not propagated to output and rightfully so, since the output of a function may be an input to something else requiring it's own set of Message headers. @@ -531,6 +552,7 @@ Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHe assertThat(result.getHeaders()).containsKey("foo"); ---- +[[type-conversion-content-type-negotiation]] === Type conversion (Content-Type negotiation) Content-Type negotiation is one of the core features of Spring Cloud Function as it allows to not only transform the incoming data to the types declared @@ -569,6 +591,7 @@ For example, HTTP POST request will have its content-type HTTP header copied to For cases when such header does not exist framework relies on the default content type as `application/json`. +[[content-type-versus-argument-type]] ==== Content Type versus Argument Type As mentioned earlier, for the framework to select the appropriate `MessageConverter`, it requires argument type and, optionally, content type information. @@ -586,6 +609,7 @@ NOTE: Do not expect `Message` to be converted into some other type based only on Remember that the `contentType` is complementary to the target type. It is a hint, which `MessageConverter` may or may not take into consideration. +[[message-converters]] ==== Message Converters `MessageConverters` define two methods: @@ -604,6 +628,7 @@ The payload of the `Message` could be any type, and it is up to the actual implementation of the `MessageConverter` to support multiple types. +[[provided-messageconverters]] ==== Provided MessageConverters As mentioned earlier, the framework already provides a stack of `MessageConverters` to handle most common use cases. @@ -662,6 +687,7 @@ public class MyCustomMessageConverter extends AbstractMessageConverter { } ---- +[[note-on-json-options]] ==== Note on JSON options In Spring Cloud Function we support Jackson and Gson mechanisms to deal with JSON. @@ -677,6 +703,7 @@ That said, the type conversion is usually transparent to the developer, however you can easily inject it into your code if needed. +[[kotlin-lambda-support]] === Kotlin Lambda support We also provide support for Kotlin lambdas (since v2.0). @@ -708,12 +735,14 @@ same rules for signature transformation outlined in "Java 8 function support" se To enable Kotlin support all you need is to add Kotlin SDK libraries on the classpath which will trigger appropriate autoconfiguration and supporting classes. +[[function-component-scan]] === Function Component Scan Spring Cloud Function will scan for implementations of `Function`, `Consumer` and `Supplier` in a package called `functions` if it exists. Using this feature you can write functions that have no dependencies on Spring - not even the `@Component` annotation is needed. If you want to use a different package, you can set `spring.cloud.function.scan.packages`. You can also use `spring.cloud.function.scan.enabled=false` to switch off the scan completely. +[[standalone-web-applications]] == Standalone Web Applications Functions could be automatically exported as HTTP endpoints. @@ -756,6 +785,7 @@ When POSTing text the response format might be different with Spring Boot 2.0 an See <> to see the details and example on how to test such application. +[[http-request-parameters]] ==== HTTP Request Parameters As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., `/{function}/{item}`). For example, `http://localhost:8080/uppercase/foo` will result in calling `uppercase` function with its input parameter being `foo`. @@ -764,6 +794,7 @@ While this is the recommended approach and the one that fits most use cases case The framework will treat HTTP request parameters similar to the HTTP headers by storing them in the `Message` headers under the header key `http_request_param` with its value being a `Map` of request parameters, so in order to access them your function input signature should accept `Message` type (e.g., `Function, String>`). For convenience we provide `HeaderUtils.HTTP_REQUEST_PARAM` constant. +[[function-mapping-rules]] === Function Mapping rules If there is only a single function (consumer etc.) in the catalog, the name in the path is optional. @@ -790,6 +821,7 @@ However there are function `foo` and `bar`. So, in this case `localhost:8080/upp This could be useful especially for cases when URL is used to communicate certain information since there will be Message header called `uri` with the value of the actual URL, giving user ability to use it for evaluation and computation. +[[function-filtering-rules]] === Function Filtering rules In situations where there are more than one function in catalog there may be a need to only export certain functions or function compositions. In that case you can use @@ -810,6 +842,7 @@ This will only export function `foo` and function `bar` regardless how many func This will only export function composition `foo|bar` and function `baz` regardless how many functions are available in catalog (e.g., `localhost:8080/foo,bar`). +[[crud-rest-with-spring-cloud-function]] === CRUD REST with Spring Cloud Function By now it should be clear that functions are exported as REST endpoints and can be invoked using various HTTP methods. In other words a single @@ -829,11 +862,13 @@ spring.cloud.function.http.DELETE=deleteById As you can see, here we’re mapping functions to various HTTP methods using the same rules as `spring.cloud.function.definition` property where “;” allows us to define several functions and “|” signifies function composition. +[[standalone-streaming-applications]] == Standalone Streaming Applications To send or receive messages from a broker (such as RabbitMQ or Kafka) you can leverage `spring-cloud-stream` project and it's integration with Spring Cloud Function. Please refer to https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/current/reference/html/spring-cloud-stream.html#spring_cloud_function[Spring Cloud Function] section of the https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] reference manual for more details and examples. +[[deploying-a-packaged-function]] == Deploying a Packaged Function Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the https://projectriff.io[Riff] Java function invoker uses this library). @@ -907,10 +942,12 @@ public MavenProperties mavenProperties() { } ``` +[[supported-packaging-scenarios]] === Supported Packaging Scenarios Currently Spring Cloud Function supports several packaging scenarios to give you the most flexibility when it comes to deploying functions. +[[simple-jar]] ==== Simple JAR This packaging option implies no dependency on anything related to Spring. @@ -954,6 +991,7 @@ package named `functions`, you can omit `spring.cloud.function.function-class` p Keep in mind the naming convention to follow when doing function lookup. For example function class `functions.UpperCaseFunction` will be available in `FunctionCatalog` under the name `upperCaseFunction`. +[[spring-boot-jar]] ==== Spring Boot JAR This packaging option implies there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR @@ -978,6 +1016,7 @@ As before all you need to do is specify `location` and `function-class` properti For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootjar[here]. You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L50[FunctionDeployerTests]. +[[spring-boot-application]] ==== Spring Boot Application This packaging option implies your JAR is complete stand alone Spring Boot application with functions as managed Spring beans. @@ -1012,10 +1051,12 @@ You can also find a corresponding test in https://github.com/spring-cloud/spring NOTE: This particular deployment option may or may not have Spring Cloud Function on it's classpath. From the deployer perspective this doesn't matter. +[[functional-bean-definitions]] == Functional Bean Definitions include::functional.adoc[leveloffset=+1] +[[serverless-platform-adapters]] == Serverless Platform Adapters As well as being able to run as a standalone process, a Spring Cloud From 64265aa3904007948060699bc06b475d8221e750 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 03/31] Copy default antora files --- docs/.github/workflows/deploy-docs.yml | 32 +++++++++++++++++++ docs/antora-playbook.yml | 43 ++++++++++++++++++++++++++ docs/antora.yml | 12 +++++++ 3 files changed, 87 insertions(+) create mode 100644 docs/.github/workflows/deploy-docs.yml create mode 100644 docs/antora-playbook.yml create mode 100644 docs/antora.yml diff --git a/docs/.github/workflows/deploy-docs.yml b/docs/.github/workflows/deploy-docs.yml new file mode 100644 index 000000000..be4b92dfc --- /dev/null +++ b/docs/.github/workflows/deploy-docs.yml @@ -0,0 +1,32 @@ +name: Deploy Docs +on: + push: + branches-ignore: [ gh-pages ] + tags: '**' + repository_dispatch: + types: request-build-reference # legacy + #schedule: + #- cron: '0 10 * * *' # Once per day at 10am UTC + workflow_dispatch: +permissions: + actions: write +jobs: + build: + runs-on: ubuntu-latest + # if: github.repository_owner == 'spring-cloud' + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: docs-build + fetch-depth: 1 + - name: Dispatch (partial build) + if: github.ref_type == 'branch' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }} + - name: Dispatch (full build) + if: github.ref_type == 'tag' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) diff --git a/docs/antora-playbook.yml b/docs/antora-playbook.yml new file mode 100644 index 000000000..9a70e676c --- /dev/null +++ b/docs/antora-playbook.yml @@ -0,0 +1,43 @@ +antora: + extensions: + - '@springio/antora-extensions/partial-build-extension' + - require: '@springio/antora-extensions/latest-version-extension' + - require: '@springio/antora-extensions/inject-collector-cache-config-extension' + - '@antora/collector-extension' + - '@antora/atlas-extension' + - require: '@springio/antora-extensions/root-component-extension' + root_component_name: 'PROJECT_WITHOUT_SPRING' + # FIXME: Run antora once using this extension to migrate to the Asciidoc Tabs syntax + # and then remove this extension + - require: '@springio/antora-extensions/tabs-migration-extension' + unwrap_example_block: always + save_result: true +site: + title: PROJECT_FULL_NAME + url: https://docs.spring.io/PROJECT_NAME/reference/ +content: + sources: + - url: ./.. + branches: HEAD + start_path: docs + worktrees: true +asciidoc: + attributes: + page-stackoverflow-url: https://stackoverflow.com/tags/spring-cloud + page-pagination: '' + hide-uri-scheme: '@' + tabs-sync-option: '@' + chomp: 'all' + extensions: + - '@asciidoctor/tabs' + - '@springio/asciidoctor-extensions' + sourcemap: true +urls: + latest_version_segment: '' +runtime: + log: + failure_level: warn + format: pretty +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip diff --git a/docs/antora.yml b/docs/antora.yml new file mode 100644 index 000000000..15b346da0 --- /dev/null +++ b/docs/antora.yml @@ -0,0 +1,12 @@ +name: PROJECT_WITHOUT_SPRING +version: true +title: PROJECT_NAME +nav: + - modules/ROOT/nav.adoc +ext: + collector: + run: + command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests + local: true + scan: + dir: ./target/classes/antora-resources/ From 0dbda442c33f9bfac9414b8e5eac6018a36e1041 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 04/31] Fix indentation for all pages --- docs/modules/ROOT/pages/README.adoc | 8 ++-- .../ROOT/pages/adapters/aws-intro.adoc | 24 +++++------ docs/modules/ROOT/pages/adapters/aws.adoc | 12 +++--- .../ROOT/pages/adapters/azure-intro.adoc | 42 +++++++++---------- .../ROOT/pages/adapters/gcp-intro.adoc | 18 ++++---- docs/modules/ROOT/pages/functional.adoc | 8 ++-- .../ROOT/pages/spring-integration.adoc | 2 +- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc index 3e3adfa2e..3db07e9f2 100644 --- a/docs/modules/ROOT/pages/README.adoc +++ b/docs/modules/ROOT/pages/README.adoc @@ -3,21 +3,21 @@ image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={branch}[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] [[introduction]] -== Introduction += Introduction include::_intro.adoc[] [[getting-started]] -== Getting Started += Getting Started include::getting-started.adoc[] [[building]] -== Building += Building include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[] [[contributing]] -== Contributing += Contributing include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] diff --git a/docs/modules/ROOT/pages/adapters/aws-intro.adoc b/docs/modules/ROOT/pages/adapters/aws-intro.adoc index 14a3d7de9..f9878866a 100644 --- a/docs/modules/ROOT/pages/adapters/aws-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/aws-intro.adoc @@ -1,7 +1,7 @@ :branch: master [[aws-lambda]] -=== AWS Lambda += AWS Lambda The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. @@ -9,7 +9,7 @@ The details of how to get stared with AWS Lambda is out of scope of this documen AWS and AWS Lambda and wants to learn what additional value spring provides. [[getting-started]] -==== Getting Started +== Getting Started One of the goals of Spring Cloud Function framework is to provide necessary infrastructure elements to enable a _simple function application_ to interact in a certain way in a particular environment. @@ -59,7 +59,7 @@ to use. The next section will explain you how you can accomplish just that. [[aws-request-handlers]] -==== AWS Request Handlers +== AWS Request Handlers The adapter has a couple of generic request handlers that you can use. The most generic is (and the one we used in the Getting Started section) is `org.springframework.cloud.function.adapter.aws.FunctionInvoker` which is the implementation of AWS's `RequestStreamHandler`. @@ -73,7 +73,7 @@ the framework will attempt to find a default following the search order where it [[aws-function-routing]] -==== AWS Function Routing +== AWS Function Routing One of the core features of Spring Cloud Function is https://docs.spring.io/spring-cloud-function/docs/{project-version}/reference/html/spring-cloud-function.html#_function_routing_and_filtering[routing] - an ability to have one special function to delegate to other functions based on the user provided routing instructions. @@ -95,12 +95,12 @@ dots with underscores and hyphens with camel case. So for example `spring.cloud and `spring.cloud.function.routing-expression` becomes `spring_cloud_function_routingExpression`. [[aws-function-routing-with-custom-runtime]] -===== AWS Function Routing with Custom Runtime +=== AWS Function Routing with Custom Runtime When using <> Function Routing works the same way. All you need is to specify `functionRouter` as AWS Handler the same way you would use the name of the function as handler. [[notes-on-jar-layout]] -==== Notes on JAR Layout +== Notes on JAR Layout You don't need the Spring Cloud Function Web or Stream adapter at runtime in Lambda, so you might need to exclude those before you create the JAR you send to AWS. A Lambda application has to be @@ -165,14 +165,14 @@ then additional transformers must be configured as part of the maven-shade-plugi ---- [[build-file-setup]] -==== Build file setup +== Build file setup In order to run Spring Cloud Function applications on AWS Lambda, you can leverage Maven or Gradle plugins offered by the cloud platform provider. [[maven]] -===== Maven +=== Maven In order to use the adapter plugin for Maven, add the plugin dependency to your `pom.xml` file: @@ -211,7 +211,7 @@ You can find the entire sample `pom.xml` file for deploying Spring Cloud Functio applications to AWS Lambda with Maven https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/pom.xml[here]. [[gradle]] -===== Gradle +=== Gradle In order to use the adapter plugin for Gradle, add the dependency to your `build.gradle` file: @@ -280,7 +280,7 @@ You can find the entire sample `build.gradle` file for deploying Spring Cloud Fu applications to AWS Lambda with Gradle https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/build.gradle[here]. [[upload]] -==== Upload +== Upload Build the sample under `spring-cloud-function-samples/function-sample-aws` and upload the `-aws` jar file to Lambda. The handler can be `example.Handler` or `org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler` (FQN of the class, _not_ a method reference, although Lambda does accept method references). @@ -306,7 +306,7 @@ NOTE: The AWS sample app is written in the "functional" style (as an `Applicatio [[type-conversion]] -==== Type Conversion +== Type Conversion Spring Cloud Function will attempt to transparently handle type conversion between the raw input stream and types declared by your function. @@ -318,7 +318,7 @@ In the event type is not known or can not be determined (e.g., `Function`) convert an incoming stream event to a generic `Map`. [[raw-input]] -====== Raw Input +==== Raw Input There are times when you may want to have access to a raw input. In this case all you need is to declare your function signature to accept `InputStream`. For example, `Function`. In this case diff --git a/docs/modules/ROOT/pages/adapters/aws.adoc b/docs/modules/ROOT/pages/adapters/aws.adoc index 31b25b7b3..77851da8e 100644 --- a/docs/modules/ROOT/pages/adapters/aws.adoc +++ b/docs/modules/ROOT/pages/adapters/aws.adoc @@ -4,12 +4,12 @@ The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. [[introduction]] -== Introduction += Introduction include::adapters/aws-intro.adoc[] [[functional-bean-definitions]] -== Functional Bean Definitions += Functional Bean Definitions Your functions will start much quicker if you can use functional bean definitions instead of `@Bean`. To do this make your main class an `ApplicationContextInitializer` and use the `registerBean()` methods in `GenericApplicationContext` to @@ -40,7 +40,7 @@ public class FuncApplication implements ApplicationContextInitializer` as an input parameter to your function a For convenience we provide AWSLambdaUtils.AWS_CONTEXT constant. [[platform-specific-features]] -== Platform Specific Features += Platform Specific Features [[http-and-api-gateway]] -=== HTTP and API Gateway +== HTTP and API Gateway AWS has some platform-specific data types, including batching of messages, which is much more efficient than processing each one individually. To make use of these types you can write a function that depends on those types. Or you can rely on Spring to extract the data from the AWS types and convert it to a Spring `Message`. To do this you tell AWS that the function is of a specific generic handler type (depending on the AWS service) and provide a bean of type `Function,Message>`, where `S` and `T` are your business data types. If there is more than one bean of type `Function` you may also need to configure the Spring Boot property `function.name` to be the name of the target bean (e.g. use `FUNCTION_NAME` as an environment variable). @@ -68,7 +68,7 @@ The supported AWS services and generic handler types are listed below: For example, to deploy behind an API Gateway, use `--handler org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler` in your AWS command line (in via the UI) and define a `@Bean` of type `Function,Message>` where `Foo` and `Bar` are POJO types (the data will be marshalled and unmarshalled by AWS using Jackson). [[custom-runtime]] -== Custom Runtime += Custom Runtime You can also benefit from https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html[AWS Lambda custom runtime] feature of AWS Lambda and Spring Cloud Function provides all the necessary components to make it easy. diff --git a/docs/modules/ROOT/pages/adapters/azure-intro.adoc b/docs/modules/ROOT/pages/adapters/azure-intro.adoc index f5e58c5a8..d357f5924 100644 --- a/docs/modules/ROOT/pages/adapters/azure-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/azure-intro.adoc @@ -1,7 +1,7 @@ :branch: master [[microsoft-azure-functions]] -== Microsoft Azure Functions += Microsoft Azure Functions :sectnums: https://azure.microsoft.com[Azure] function adapter for deploying `Spring Cloud Function` applications as native Azure Java Functions. @@ -21,12 +21,12 @@ This adapter hides the Azure annotations complexity and uses the familiar https: For further information follow the <> section below. [[azure-adapter]] -== Azure Adapter += Azure Adapter Provides `Spring` & `Spring Cloud Function` integration for Azure Functions. [[dependencies]] -=== Dependencies +== Dependencies In order to enable the Azure Function integration add the azure adapter dependency to your `pom.xml` or `build.gradle` files: @@ -55,7 +55,7 @@ dependencies { NOTE: version `4.0.0+` is required. Having the adapter on the classpath activates the Azure Java Worker integration. [[azure.development.guidelines]] -=== Development Guidelines +== Development Guidelines Use the `@Component` (or `@Service`) annotation to turn any exiting Azure Function class (e.g. with `@FunctionName` handlers) into a Spring component. Then you can auto-wire the required dependencies (or the <> for Spring Cloud Function composition) and use those inside the Azure function handlers. @@ -131,7 +131,7 @@ public class HttpTriggerDemoApplication { <2> Functions auto-wired and used in the Azure function handlers. [[function-catalog]] -==== Function Catalog +=== Function Catalog The Spring Cloud Function supports a range of type signatures for user-defined functions, while providing a consistent execution model. For this it uses the <> to transform all user defined functions into a canonical representation. @@ -142,7 +142,7 @@ But those are treated as plain Java class instances, not as a canonical Spring C To leverage Spring Cloud Function and have access to the canonical function representations, you need to auto-wire the `FunctionCatalog` and use it in your handler, like the `functionCatalog` instance the `springCloudFunction()` handler above. [[accessing-azure-executioncontext]] -==== Accessing Azure ExecutionContext +=== Accessing Azure ExecutionContext Some time there is a need to access the target execution context provided by the Azure runtime in the form of `com.microsoft.azure.functions.ExecutionContext`. For example one of such needs is logging, so it can appear in the Azure console. @@ -182,7 +182,7 @@ public Function, String> uppercase(JsonMapper mapper) { [[azure.configuration]] -=== Configuration +== Configuration To run your function applications on Microsoft Azure, you have to provide the necessary configurations, such as `function.json` and `host.json`, and adhere to the compulsory https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#folder-structure[packaging format]. @@ -192,7 +192,7 @@ IMPORTANT: The Azure https://learn.microsoft.com/en-us/azure/azure-functions/fun The <> section below explains how to handle this. [[azure-maven/gradle-plugins]] -==== Azure Maven/Gradle Plugins +=== Azure Maven/Gradle Plugins Azure provides https://github.com/microsoft/azure-maven-plugins/tree/develop/azure-functions-maven-plugin[Maven] and https://github.com/microsoft/azure-gradle-plugins/tree/master/azure-functions-gradle-plugin[Gradle] plugins to process the annotated classes, generate the necessary configurations and produce the expected package layout. Plugins are used to set the platform, runtime and app-settings properties like this: @@ -276,7 +276,7 @@ azurefunctions { More information about the runtime configurations: https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#java-versions[Java Versions], https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#specify-the-deployment-os[Deployment OS]. [[disable.spring.boot.plugin]] -==== Disable Spring Boot Plugin +=== Disable Spring Boot Plugin Expectedly, the Azure Functions run inside the Azure execution runtime, not inside the SpringBoot runtime! Furthermore, Azure expects a specific packaging format, generated by the Azure Maven/Gradle plugins, that is not compatible with the default Spring Boot packaging. @@ -298,7 +298,7 @@ You have to either disable the SpringBoot Maven/Gradle plugin or use the https:/ ---- [[star-class-configuration]] -==== Main-Class Configuration +=== Main-Class Configuration Specify the `Main-Class`/`Start-Class` to point to your Spring application entry point, such as the <> class in the example above. @@ -334,7 +334,7 @@ For local runs, add the `MAIN_CLASS` variable to your `local.settings.json` file IMPORTANT: If the `MAIN_CLASS` variable is not set, the Azure adapter lookups the `MANIFEST/META-INFO` attributes from the jars found on the classpath and selects the first `Main-Class:` annotated with either a `@SpringBootApplication` or `@SpringBootConfiguration` annotation. [[metadata-configuration]] -==== Metadata Configuration +=== Metadata Configuration You can use a shared https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json[host.json] file to configure the function app. @@ -354,7 +354,7 @@ The host.json metadata file contains configuration options that affect all funct TIP: If the file is not in the project top folder you need to configure your plugins accordingly (like `hostJson` maven attribute). [[samples]] -=== Samples +== Samples Here is a list of various Spring Cloud Function Azure Adapter samples you can explore: @@ -365,7 +365,7 @@ Here is a list of various Spring Cloud Function Azure Adapter samples you can ex - https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-kafka-trigger[ Kafka Trigger & Output Binding (Maven)]. [[azure.web.adapter]] -== Azure Web Adapter += Azure Web Adapter For, pure, Web-based function applications, you can replace the generic `adapter-azure` with the specialized https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web[spring-cloud-function-adapter-azure-web]. The Azure Web Adapter can deploy any Spring Web application as a native Azure function, using the HttpTrigger internally. @@ -398,19 +398,19 @@ The same <> and <> instru [[samples]] -=== Samples +== Samples For further information, explore the following, Azure Web Adapter, sample: - https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-web[ Azure Web Adapter (Maven)]. [[azure.usage]] -== Usage += Usage Common instructions for building and deploying both, `Azure Adapter` and `Azure Web Adapter` type of applications. [[build]] -=== Build +== Build ==== [source,xml,indent=0,subs="verbatim,attributes",role="primary"] @@ -427,7 +427,7 @@ Common instructions for building and deploying both, `Azure Adapter` and `Azure ==== [[running-locally]] -=== Running locally +== Running locally To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here]). For some configuration you would need the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator[Azurite emulator] as well. @@ -449,7 +449,7 @@ Then run the sample: ==== [[running-on-azure]] -=== Running on Azure +== Running on Azure Make sure you are logged in your Azure account. @@ -474,7 +474,7 @@ and deploy ==== [[debug-locally]] -=== Debug locally +== Debug locally Run the function in debug mode. @@ -530,14 +530,14 @@ Here is snippet for a `VSCode` remote debugging configuration: ---- [[functioninvoker-deprecated]] -== FunctionInvoker (deprecated) += FunctionInvoker (deprecated) WARNING: The legacy `FunctionInvoker` programming model is deprecated and will not be supported going forward. For additional documentation and samples about the Function Integration approach follow the https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure/[azure-sample] README and code. [[relevant-links]] -== Relevant Links += Relevant Links - https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/getting-started-with-spring-cloud-function-in-azure[Spring Cloud Function in Azure] - https://spring.io/blog/2023/02/24/spring-cloud-function-for-azure-function[Spring Cloud Function for Azure Function (blog)] diff --git a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc index 4826d6d58..af9d79821 100644 --- a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc @@ -1,13 +1,13 @@ :branch: master [[google-cloud-functions]] -=== Google Cloud Functions += Google Cloud Functions The Google Cloud Functions adapter enables Spring Cloud Function apps to run on the https://cloud.google.com/functions[Google Cloud Functions] serverless platform. You can either run the function locally using the open source https://github.com/GoogleCloudPlatform/functions-framework-java[Google Functions Framework for Java] or on GCP. [[project-dependencies]] -==== Project Dependencies +== Project Dependencies Start by adding the `spring-cloud-function-adapter-gcp` dependency to your project. @@ -65,12 +65,12 @@ NOTE: The function target should always be set to `org.springframework.cloud.fun A full example of a working `pom.xml` can be found in the https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-gcp-http/pom.xml[Spring Cloud Functions GCP sample]. [[http-functions]] -==== HTTP Functions +== HTTP Functions Google Cloud Functions supports deploying https://cloud.google.com/functions/docs/writing/http[HTTP Functions], which are functions that are invoked by HTTP request. The sections below describe instructions for deploying a Spring Cloud Function as an HTTP Function. [[getting-started]] -===== Getting Started +=== Getting Started Let’s start with a simple Spring Cloud Function example: @@ -111,7 +111,7 @@ curl http://localhost:8080/ -d "hello" ---- [[deploy-to-gcp]] -===== Deploy to GCP +=== Deploy to GCP Start by packaging your application. @@ -164,7 +164,7 @@ public Function> function() { [[background-functions]] -==== Background Functions +== Background Functions Google Cloud Functions also supports deploying https://cloud.google.com/functions/docs/writing/background[Background Functions] which are invoked indirectly in response to an event, such as a message on a https://cloud.google.com/pubsub[Cloud Pub/Sub] topic, a change in a https://cloud.google.com/storage[Cloud Storage] bucket, or a https://firebase.google.com/[Firebase] event. @@ -174,7 +174,7 @@ The sections below describe the process for writing a Cloud Pub/Sub topic backgr However, there are a number of different event types that can trigger a background function to execute which are not discussed here; these are described in the https://cloud.google.com/functions/docs/calling[Background Function triggers documentation]. [[getting-started]] -===== Getting Started +=== Getting Started Let’s start with a simple Spring Cloud Function which will run as a GCF background function: @@ -267,7 +267,7 @@ curl localhost:8080 -H "Content-Type: application/json" -d '{"data":"hello"}' Verify that the function was invoked by viewing the logs. [[deploy-to-gcp]] -===== Deploy to GCP +=== Deploy to GCP In order to deploy your background function to GCP, first package your application. @@ -296,7 +296,7 @@ Google Cloud Function will now invoke the function every time a message is publi For a walkthrough on testing and verifying your background function, see the instructions for running the https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-background/[GCF Background Function sample]. [[sample-functions]] -==== Sample Functions +== Sample Functions The project provides the following sample functions as reference: diff --git a/docs/modules/ROOT/pages/functional.adoc b/docs/modules/ROOT/pages/functional.adoc index 7e4e89736..68958a89c 100644 --- a/docs/modules/ROOT/pages/functional.adoc +++ b/docs/modules/ROOT/pages/functional.adoc @@ -1,7 +1,7 @@ Spring Cloud Function supports a "functional" style of bean declarations for small apps where you need fast startup. The functional style of bean declaration was a feature of Spring Framework 5.0 with significant enhancements in 5.1. [[comparing-functional-with-traditional-bean-definitions]] -== Comparing Functional with Traditional Bean Definitions += Comparing Functional with Traditional Bean Definitions Here's a vanilla Spring Cloud Function application from with the familiar `@Configuration` and `@Bean` declaration style: @@ -115,7 +115,7 @@ public void initialize(GenericApplicationContext context) { ---- [[limitations-of-functional-bean-declaration]] -== Limitations of Functional Bean Declaration += Limitations of Functional Bean Declaration Most Spring Cloud Function apps have a relatively small scope compared to the whole of Spring Boot, so we are able to adapt it to these functional bean definitions easily. If you step outside that limited scope, @@ -131,7 +131,7 @@ functional mode" using `spring.functional.enabled=false` so that Spring Boot can Spring Cloud Function supports visualization of functions available in `FunctionCatalog` through Actuator endpoints as well as programmatic way. [[programmatic-way]] -==== Programmatic way +=== Programmatic way To see function available within your application context programmatically all you need is access to `FunctionCatalog`. There you can finds methods to get the size of the catalog, lookup functions as well as list the names of all the available functions. @@ -147,7 +147,7 @@ Set names = functionCatalog.getNames(null); will list the names of all t ---- [[actuator]] -==== Actuator +=== Actuator Since actuator and web are optional, you must first add one of the web dependencies as well as add the actuator dependency manually. The following example shows how to add the dependency for the Web framework: diff --git a/docs/modules/ROOT/pages/spring-integration.adoc b/docs/modules/ROOT/pages/spring-integration.adoc index 52c6d1499..670aa8d98 100644 --- a/docs/modules/ROOT/pages/spring-integration.adoc +++ b/docs/modules/ROOT/pages/spring-integration.adoc @@ -1,5 +1,5 @@ [[spring-integration]] -== Spring Integration Interaction += Spring Integration Interaction https://spring.io/projects/spring-integration[Spring Integration Framework] extends the Spring programming model to support the well-known Enterprise Integration Patterns. It enables lightweight messaging within Spring-based applications and supports integration with external systems via declarative adapters. From 1399a2e458a72d3e91bb05e28df98de447fa9865 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 05/31] Split files --- .../ROOT/pages/spring-cloud-function.adoc | 1057 ----------------- .../deploying-a-packaged.adoc | 183 +++ .../functional-bean-definitions.adoc | 5 + .../getting-started.adoc | 5 + .../spring-cloud-function/introduction.adoc | 7 + .../programming-model.adoc | 717 +++++++++++ .../serverless-platform-adapters.adoc | 14 + .../standalone-streaming-applications.adoc | 6 + .../standalone-web-applications.adoc | 120 ++ 9 files changed, 1057 insertions(+), 1057 deletions(-) create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc create mode 100644 docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc diff --git a/docs/modules/ROOT/pages/spring-cloud-function.adoc b/docs/modules/ROOT/pages/spring-cloud-function.adoc index 9cff8a176..f44e47630 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function.adoc @@ -13,1060 +13,3 @@ Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin :nofooter: :branch: master -[[introduction]] -== Introduction - -include::_intro.adoc[] - -include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing-docs.adoc[] - -[[getting-started]] -== Getting Started - -include::getting-started.adoc[] - -[[programming-model]] -== Programming model - -[[function.catalog]] - -[[function-catalog-and-flexible-function-signatures]] -=== Function Catalog and Flexible Function Signatures - -One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions, -while providing a consistent execution model. -That's why all user defined functions are transformed into a canonical representation by `FunctionCatalog`. - -While users don't normally have to care about the `FunctionCatalog` at all, it is useful to know what -kind of functions are supported in user code. - -It is also important to understand that Spring Cloud Function provides first class support for reactive API -provided by https://projectreactor.io/[Project Reactor] allowing reactive primitives such as `Mono` and `Flux` -to be used as types in user defined functions providing greater flexibility when choosing programming model for -your function implementation. -Reactive programming model also enables functional support for features that would be otherwise difficult to impossible to implement -using imperative programming style. For more on this please read <> section. - -[[java-8-function-support]] -=== Java 8 function support - -Spring Cloud Function embraces and builds on top of the 3 core functional interfaces defined by Java -and available to us since Java 8. - -- Supplier -- Function -- Consumer - -To avoid constantly mentioning `Supplier`, `Function` and `Consumer` we’ll refer to them a Functional beans for the rest of this manual where appropriate. - -In a nutshell, any bean in your Application Context that is Functional bean will lazily be registered with `FunctionCatalog`. -This means that it could benefit from all of the additional features described in this reference manual. - -In a simplest of application all you need to do is to declare `@Bean` of type `Supplier`, `Function` or `Consumer` in your application configuration. -Then you can access `FunctionCatalog` and lookup a particular function based on its name. - -For example: - - -[source, test] ----- -@Bean -public Function uppercase() { - return value -> value.toUpperCase(); -} - -. . . - -FunctionCatalog catalog = applicationContext.getBean(FunctionCatalog.class); -Function uppercase = catalog.lookup(“uppercase”); ----- - -Important to understand that given that `uppercase` is a bean, you can certainly get it form the `ApplicationContext` directly, but all you will get is just your bean as you declared it without any extra features provided by SCF. When you do lookup of a function via `FunctionCatalog`, the instance you will receive is wrapped (instrumented) with additional features (i.e., type conversion, composition etc.) described in this manual. Also, it is important to understand that a typical user does not use Spring Cloud Function directly. Instead a typical user implements Java `Function/Supplier/Consumer` with the idea of using it in different execution contexts without additional work. For example the same java function could be represented as _REST endpoint_ or _Streaming message handler_ or _AWS Lambda_ and more via Spring Cloud Function provided -adapters as well as other frameworks using Spring Cloud Function as the core programming model (e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]) -So in summary Spring Cloud Function instruments java functions with additional features to be utilised in variety of execution contexts. - - -[[function-definition]] -==== Function definition -While the previous example shows you how to lookup function in FunctionCatalog programmatically, in a typical integration case where Spring Cloud Function used as programming model by another framework (e.fg. Spring Cloud Stream), you declare which functions to use via `spring.cloud.function.definition` property. Knowing that it is important to understand some default behaviour when it comes to discovering functions in `FunctionCatalog`. For example, if you only have one Functional bean in your `ApplicationContext`, the `spring.cloud.function.definition` property typically will not be required, since a single function in `FunctionCatalog` can be looked up by an empty name or any name. For example, assuming that `uppercase` is the only function in your catalog, it can be looked up as `catalog.lookup(null)`, `catalog.lookup(“”)`, `catalog.lookup(“foo”)` -That said, for cases where you are using framework such as Spring Cloud Stream which uses `spring.cloud.function.definition` it is best practice and recommended to always use `spring.cloud.function.definition` property. - -For example, - -[source, test] ----- -spring.cloud.function.definition=uppercase ----- - -[[filtering-ineligible-functions]] -==== Filtering ineligible functions -A typical Application Context may include beans that are valid java functions, but not intended to be candidates to be registered with `FunctionCatalog`. -Such beans could be auto-configurations from other projects or any other beans that qualify to be Java functions. -The framework provides default filtering of known beans that should not be candidates for registration with function catalog. -You can also add to this list additional beans by providing coma delimited list of bean definition names using -`spring.cloud.function.ineligible-definitions` property. - -For example, - -[source, test] ----- -spring.cloud.function.ineligible-definitions=foo,bar ----- - -[[supplier]] -==== Supplier -Supplier can be _reactive_ - `Supplier>` -or _imperative_ - `Supplier`. From the invocation standpoint this should make no difference -to the implementor of such Supplier. However, when used within frameworks -(e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]), Suppliers, especially reactive, -often used to represent the source of the stream, therefore they are invoked once to get the stream (e.g., Flux) -to which consumers can subscribe to. In other words such suppliers represent an equivalent of an _infinite stream_. -However, the same reactive suppliers can also represent _finite_ stream(s) (e.g., result set on the polled JDBC data). -In those cases such reactive suppliers must be hooked up to some polling mechanism of the underlying framework. - -To assist with that Spring Cloud Function provides a marker annotation -`org.springframework.cloud.function.context.PollableBean` to signal that such supplier produces a -finite stream and may need to be polled again. That said, it is important to understand that Spring Cloud Function itself -provides no behavior for this annotation. - -In addition `PollableBean` annotation exposes a _splittable_ attribute to signal that produced stream -needs to be split (see https://www.enterpriseintegrationpatterns.com/patterns/messaging/Sequencer.html[Splitter EIP]) - -Here is the example: - -[source, java] ----- -@PollableBean(splittable = true) -public Supplier> someSupplier() { - return () -> { - String v1 = String.valueOf(System.nanoTime()); - String v2 = String.valueOf(System.nanoTime()); - String v3 = String.valueOf(System.nanoTime()); - return Flux.just(v1, v2, v3); - }; -} ----- - -[[function]] -==== Function -Function can also be written in imperative or reactive way, yet unlike Supplier and Consumer there are -no special considerations for the implementor other then understanding that when used within frameworks -such as https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] and others, reactive function is -invoked only once to pass a reference to the stream (Flux or Mono) and imperative is invoked once per event. - -[[consumer]] -==== Consumer -Consumer is a little bit special because it has a `void` return type, -which implies blocking, at least potentially. Most likely you will not -need to write `Consumer>`, but if you do need to do that, -remember to subscribe to the input flux. - -[[function-composition]] -=== Function Composition -Function Composition is a feature that allows one to compose several functions into one. -The core support is based on function composition feature available with https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#andThen-java.util.function.Function-[Function.andThen(..)] -support available since Java 8. However on top of it, we provide few additional features. - -[[declarative-function-composition]] -==== Declarative Function Composition - -This feature allows you to provide composition instruction in a declarative way using `|` (pipe) or `,` (comma) delimiter -when providing `spring.cloud.function.definition` property. - -For example ----- ---spring.cloud.function.definition=uppercase|reverse ----- -Here we effectively provided a definition of a single function which itself is a composition of -function `uppercase` and function `reverse`. In fact that is one of the reasons why the property name is _definition_ and not _name_, -since the definition of a function can be a composition of several named functions. -And as mentioned you can use `,` instead of pipe (such as `...definition=uppercase,reverse`). - -[[composing-non-functions]] -==== Composing non-Functions -Spring Cloud Function also supports composing Supplier with `Consumer` or `Function` as well as `Function` with `Consumer`. -What's important here is to understand the end product of such definitions. -Composing Supplier with Function still results in Supplier while composing Supplier with Consumer will effectively render Runnable. -Following the same logic composing Function with Consumer will result in Consumer. - -And of course you can't compose uncomposable such as Consumer and Function, Consumer and Supplier etc. - - -[[function-routing-and-filtering]] -=== Function Routing and Filtering - -Since version 2.2 Spring Cloud Function provides routing feature allowing -you to invoke a single function which acts as a router to an actual function you wish to invoke -This feature is very useful in certain FAAS environments where maintaining configurations -for several functions could be cumbersome or exposing more than one function is not possible. - -The `RoutingFunction` is registered in _FunctionCatalog_ under the name `functionRouter`. For simplicity -and consistency you can also refer to `RoutingFunction.FUNCTION_NAME` constant. - -This function has the following signature: - -[source, java] ----- -public class RoutingFunction implements Function { -. . . -} ----- -The routing instructions could be communicated in several ways. We support providing instructions via Message headers, System -properties as well as pluggable strategy. So let's look at some of the details - -[[messageroutingcallback]] -==== MessageRoutingCallback - -The `MessageRoutingCallback` is a strategy to assist with determining the name of the route-to function definition. - -[source, java] ----- -public interface MessageRoutingCallback { - FunctionRoutingResult routingResult(Message message); - . . . -} ----- - -All you need to do is implement and register it as a bean to be picked up by the `RoutingFunction`. -For example: - -[source, java] ----- -@Bean -public MessageRoutingCallback customRouter() { - return new MessageRoutingCallback() { - @Override - public FunctionRoutingResult routingResult(Message message) { - return new FunctionRoutingResult((String) message.getHeaders().get("func_name")); - } - }; -} ----- - -In the preceding example you can see a very simple implementation of `MessageRoutingCallback` which determines the function definition from -`func_name` Message header of the incoming Message and returns the instance of `FunctionRoutingResult` containing the definition of function to invoke. - -*Message Headers* - -If the input argument is of type `Message`, you can communicate routing instruction by setting one of -`spring.cloud.function.definition` or `spring.cloud.function.routing-expression` Message headers. -As the name of the property suggests `spring.cloud.function.routing-expression` relies on Spring Expression Language (SpEL). -For more static cases you can use `spring.cloud.function.definition` header which allows you to provide -the name of a single function (e.g., `...definition=foo`) or a composition instruction (e.g., `...definition=foo|bar|baz`). -For more dynamic cases you can use `spring.cloud.function.routing-expression` header and provide SpEL expression that should resolve -into definition of a function (as described above). - -NOTE: SpEL evaluation context's root object is the -actual input argument, so in the case of `Message` you can construct expression that has access -to both `payload` and `headers` (e.g., `spring.cloud.function.routing-expression=headers.function_name`). - -IMPORTANT: SpEL allows user to provide string representation of Java code to be executed. Given that the `spring.cloud.function.routing-expression` could be provided via Message headers means that ability to set such expression could be exposed to the end user (i.e., HTTP Headers when using web module) which could result in some problems (e.g., malicious code). To manage that, all expressions coming via Message headers will only be evaluated against `SimpleEvaluationContext` which has limited functionality and designed to only evaluate the context object (Message in our case). On the other hand, all expressions that are set via property or system variable are evaluated against `StandardEvaluationContext`, which allows for full flexibility of Java language. -While setting expression via system/application property or environment variable is generally considered to be secure as it is not exposed to the end user in normal cases, there are cases where visibility as well as capability to update system, application and environment variables are indeed exposed to the end user via Spring Boot Actuator endpoints provided either by some of the Spring projects or third parties or custom implementation by the end user. Such endpoints must be secured using industry standard web security practices. -Spring Cloud Function does not expose any of such endpoints. - -In specific execution environments/models the adapters are responsible to translate and communicate -`spring.cloud.function.definition` and/or `spring.cloud.function.routing-expression` via Message header. -For example, when using _spring-cloud-function-web_ you can provide `spring.cloud.function.definition` as an HTTP -header and the framework will propagate it as well as other HTTP headers as Message headers. - -*Application Properties* - -Routing instruction can also be communicated via `spring.cloud.function.definition` -or `spring.cloud.function.routing-expression` as application properties. The rules described in the -previous section apply here as well. The only difference is you provide these instructions as -application properties (e.g., `--spring.cloud.function.definition=foo`). - -NOTE: It is important to understand that providing `spring.cloud.function.definition` -or `spring.cloud.function.routing-expression` as Message headers will only work for imperative functions (e.g., `Function`). -That is to say that we can _only_ route ***per-message*** with imperative functions. With reactive functions we can not route -***per-message***. Therefore you can only provide your routing instructions as Application Properties. -It's all about unit-of-work. In imperative function unit of work is Message so we can route based on such unit-of-work. -With reactive function unit-of-work is the entire stream, so we'll act only on the instruction provided via application -properties and route the entire stream. - -*Order of priority for routing instructions* - -Given that we have several mechanisms of providing routing instructions it is important to understand the priorities for -conflict resolutions in the event multiple mechanisms are used at the same time, so here is the order: - -1. `MessageRoutingCallback` (If function is imperative will take over regardless if anything else is defined) -2. Message Headers (If function is imperative and no `MessageRoutingCallback` provided) -3. Application Properties (Any function) - -*Unroutable Messages* - -In the event route-to function is not available in catalog you will get an exception stating that. - -There are cases when such behavior is not desired and you may want to have some "catch-all" type function which can handle such messages. -To accomplish that, framework provides `org.springframework.cloud.function.context.DefaultMessageRoutingHandler` strategy. All you need to do is register it as a bean. -Its default implementation will simply log the fact that the message is un-routable, but will allow message flow to proceed without the exception, effectively dropping the un-routable message. -If you want something more sophisticated all you need to do is provide your own implementation of this strategy and register it as a bean. - -[source, java] ----- -@Bean -public DefaultMessageRoutingHandler defaultRoutingHandler() { - return new DefaultMessageRoutingHandler() { - @Override - public void accept(Message message) { - // do something really cool - } - }; -} ----- - -[[function-filtering]] -==== Function Filtering -Filtering is the type of routing where there are only two paths - 'go' or 'discard'. In terms of functions it mean -you only want to invoke a certain function if some condition returns 'true', otherwise you want to discard input. -However, when it comes to discarding input there are many interpretation of what it could mean in the context of your application. -For example, you may want to log it, or you may want to maintain the counter of discarded messages. you may also want to do nothing at all. -Because of these different paths, we do not provide a general configuration option for how to deal with discarded messages. -Instead we simply recommend to define a simple Consumer which would signify the 'discard' path: - -[source, java] ----- -@Bean -public Consumer devNull() { - // log, count or whatever -} ----- -Now you can have routing expression that really only has two paths effectively becoming a filter. For example: - -[source, text] ----- ---spring.cloud.function.routing-expression=headers.contentType.toString().equals('text/plain') ? 'echo' : 'devNull' ----- -Every message that does not fit criteria to go to 'echo' function will go to 'devNull' where you can simply do nothing with it. -The signature `Consumer` will also ensure that no type conversion will be attempted resulting in almost no execution overhead. - - -IMPORTANT: When dealing with reactive inputs (e.g., Publisher), routing instructions must only be provided via Function properties. This is -due to the nature of the reactive functions which are invoked only once to pass a Publisher and the rest -is handled by the reactor, hence we can not access and/or rely on the routing instructions communicated via individual -values (e.g., Message). - -[[multiple-routers]] -==== Multiple Routers - -By default the framework will always have a single routing function configured as described in previous sections. However, there are times when you may need more than one routing function. -In that case you can create your own instance of the `RoutingFunction` bean in addition to the existing one as long as you give it a name other than `functionRouter`. - -You can pass `spring.cloud.function.routing-expression` or `spring.cloud.function.definition` to RoutinFunction as key/value pairs in the map. - -Here is a simple example - ----- -@Configuration -protected static class MultipleRouterConfiguration { - - @Bean - RoutingFunction mySpecialRouter(FunctionCatalog functionCatalog, BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) { - Map propertiesMap = new HashMap<>(); - propertiesMap.put(FunctionProperties.PREFIX + ".routing-expression", "'reverse'"); - return new RoutingFunction(functionCatalog, propertiesMap, new BeanFactoryResolver(beanFactory), routingCallback); - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function uppercase() { - return String::toUpperCase; - } -} ----- - -and a test that demonstrates how it works - -` ----- -@Test -public void testMultipleRouters() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "'uppercase'"); - FunctionCatalog functionCatalog = this.configureCatalog(MultipleRouterConfiguration.class); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("HELLO"); - - function = functionCatalog.lookup("mySpecialRouter"); - assertThat(function).isNotNull(); - message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); -} ----- - -[[input/output-enrichment]] -=== Input/Output Enrichment - -There are often times when you need to modify or refine an incoming or outgoing Message and to keep your code clean of non-functional concerns. You don’t want to do it inside of your business logic. - -You can always accomplish it via <>. Such approach provides several benefits: - -- It allows you to isolate this non-functional concern into a separate function which you can compose with the business function as function definition. -- It provides you with complete freedom (and danger) as to what you can modify before incoming message reaches the actual business function. - -[source, java] ----- -@Bean -public Function, Message> enrich() { - return message -> MessageBuilder.fromMessage(message).setHeader("foo", "bar").build(); -} - -@Bean -public Function, Message> myBusinessFunction() { - // do whatever -} ----- - -And then compose your function by providing the following function definition `enrich|myBusinessFunction`. - -While the described approach is the most flexible, it is also the most involved as it requires you to write some code, make it a bean or -manually register it as a function before you can compose it with the business function as you can see from the preceding example. - -But what if modifications (enrichments) you are trying to make are trivial as they are in the preceding example? Is there a simpler and more dynamic and configurable - mechanism to accomplish the same? - -Since version 3.1.3, the framework allows you to provide SpEL expression to enrich individual message headers for both input going into function and -and output coming out of it. Let’s look at one of the tests as the example. - -[source, java] ----- -@Test -public void testMixedInputOutputHeaderMapping() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut1='hello1'", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut2=headers.contentType", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key1=headers.path.split('/')[0]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key2=headers.path.split('/')[1]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key3=headers.path")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("split"); - Message result = (Message) function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setHeader("path", "foo/bar/baz").build()); - assertThat(result.getHeaders().containsKey("keyOut1")).isTrue(); - assertThat(result.getHeaders().get("keyOut1")).isEqualTo("hello1"); - assertThat(result.getHeaders().containsKey("keyOut2")).isTrue(); - assertThat(result.getHeaders().get("keyOut2")).isEqualTo("application/json"); - } -} ----- - -Here you see a properties called `input-header-mapping-expression` and `output-header-mapping-expression` preceded by the name of the function (i.e., `split`) and followed by the name of the message header key you want to set and the value as SpEL expression. The first expression (for 'keyOut1') is literal SpEL expressions enclosed in single quotes, effectively setting 'keyOut1' to value `hello1`. The `keyOut2` is set to the value of existing 'contentType' header. - -You can also observe some interesting features in the input header mapping where we actually splitting a value of the existing header 'path', setting individual values of key1 and key2 to the values of split elements based on the index. - -NOTE: if for whatever reason the provided expression evaluation fails, the execution of the function will proceed as if nothing ever happen. -However you will see the WARN message in your logs informing you about it - -[source, text] ----- -o.s.c.f.context.catalog.InputEnricher : Failed while evaluating expression "hello1" on incoming message. . . ----- - -In the event you are dealing with functions that have multiple inputs (next section), you can use index immediately after `input-header-mapping-expression` - -[source, text] ----- ---spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1=‘hello1' ---spring.cloud.function.configuration.echo.input-header-mapping-expression[1].key2='hello2' ----- - -[[function-arity]] -=== Function Arity - -There are times when a stream of data needs to be categorized and organized. For example, -consider a classic big-data use case of dealing with unorganized data containing, let’s say, -‘orders’ and ‘invoices’, and you want each to go into a separate data store. -This is where function arity (functions with multiple inputs and outputs) support -comes to play. - -Let’s look at an example of such a function (full implementation details are available -https://github.com/spring-cloud/spring-cloud-stream/blob/master/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/MultipleInputOutputFunctionTests.java#L342[here]), - -[source, java] ----- -@Bean -public Function, Tuple2, Flux>> organise() { - return flux -> ...; -} ----- - -Given that Project Reactor is a core dependency of SCF, we are using its Tuple library. -Tuples give us a unique advantage by communicating to us both _cardinality_ and _type_ information. -Both are extremely important in the context of SCSt. Cardinality lets us know -how many input and output bindings need to be created and bound to the corresponding -inputs and outputs of a function. Awareness of the type information ensures proper type -conversion. - -Also, this is where the ‘index’ part of the naming convention for binding -names comes into play, since, in this function, the two output binding -names are `organise-out-0` and `organise-out-1`. - -IMPORTANT: IMPORTANT: At the moment, function arity is *only* supported for reactive functions -(`Function...>, TupleN...>>`) centered on Complex event processing -where evaluation and computation on confluence of events typically requires view into a -stream of events rather than single event. - -[[input-header-propagation]] -=== Input Header propagation - -In a typical scenario input Message headers are not propagated to output and rightfully so, since the output of a function may be an input to something else requiring it's own set of Message headers. -However, there are times when such propagation may be necessary so Spring Cloud Function provides several mechanisms to accomplish this. - -First you can always copy headers manually. For example, if you have a Function with the signature that takes `Message` and returns `Message` (i.e., `Function`), you can simply and selectively copy headers yourselves. Remember, if your function returns Message, the framework will not do anything to it other then properly converting its payload. -However, such approach may prove to be a bit tedious, especially in cases when you simply want to copy all headers. -To assist with cases like this we provide a simple property that would allow you to set a boolean flag on a function where you want input headers to be propagated. -The property is `copy-input-headers`. - -For example, let's assume you have the following configuration: - -[source, java] ----- -@EnableAutoConfiguration -@Configuration -protected static class InputHeaderPropagationConfiguration { - - @Bean - public Function uppercase() { - return x -> x.toUpperCase(); - } -} ----- - -As you know you can still invoke this function by sending a Message to it (framework will take care of type conversion and payload extraction) - -By simply setting `spring.cloud.function.configuration.uppercase.copy-input-headers` to `true`, the following assertion will be true as well - ----- -Function, Message> uppercase = catalog.lookup("uppercase", "application/json"); -Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHeader("foo", "bar").build()); -assertThat(result.getHeaders()).containsKey("foo"); ----- - -[[type-conversion-content-type-negotiation]] -=== Type conversion (Content-Type negotiation) - -Content-Type negotiation is one of the core features of Spring Cloud Function as it allows to not only transform the incoming data to the types declared -by the function signature, but to do the same transformation during function composition making otherwise un-composable (by type) functions composable. - -To better understand the mechanics and the necessity behind content-type negotiation, we take a look at a very simple use case by -using the following function as an example: - -[source, java] ----- -@Bean -public Function personFunction {..} ----- - -The function shown in the preceding example expects a `Person` object as an argument and produces a String type as an output. If such function is -invoked with the type `Person`, than all works fine. But typically function plays a role of a handler for the incoming data which most often comes -in the raw format such as `byte[]`, `JSON String` etc. In order for the framework to succeed in passing the incoming data as an argument to -this function, it has to somehow transform the incoming data to a `Person` type. - -Spring Cloud Function relies on two native to Spring mechanisms to accomplish that. - -. _MessageConverter_ - to convert from incoming Message data to a type declared by the function. -. _ConversionService_ - to convert from incoming non-Message data to a type declared by the function. - -This means that depending on the type of the raw data (Message or non-Message) Spring Cloud Function will apply one or the other mechanisms. - -For most cases when dealing with functions that are invoked as part of some other request (e.g., HTTP, Messaging etc) the framework relies on `MessageConverters`, -since such requests already converted to Spring `Message`. In other words, the framework locates and applies the appropriate `MessageConverter`. -To accomplish that, the framework needs some instructions from the user. One of these instructions is already provided by the signature of the function -itself (Person type). Consequently, in theory, that should be (and, in some cases, is) enough. However, for the majority of use cases, in order to -select the appropriate `MessageConverter`, the framework needs an additional piece of information. That missing piece is `contentType` header. - -Such header usually comes as part of the Message where it is injected by the corresponding adapter that created such Message in the first place. -For example, HTTP POST request will have its content-type HTTP header copied to `contentType` header of the Message. - -For cases when such header does not exist framework relies on the default content type as `application/json`. - - -[[content-type-versus-argument-type]] -==== Content Type versus Argument Type - -As mentioned earlier, for the framework to select the appropriate `MessageConverter`, it requires argument type and, optionally, content type information. -The logic for selecting the appropriate `MessageConverter` resides with the argument resolvers which trigger right before the invocation of the user-defined -function (which is when the actual argument type is known to the framework). -If the argument type does not match the type of the current payload, the framework delegates to the stack of the -pre-configured `MessageConverters` to see if any one of them can convert the payload. - -The combination of `contentType` and argument type is the mechanism by which framework determines if message can be converted to a target type by locating -the appropriate `MessageConverter`. -If no appropriate `MessageConverter` is found, an exception is thrown, which you can handle by adding a custom `MessageConverter` -(see `<>`). - -NOTE: Do not expect `Message` to be converted into some other type based only on the `contentType`. -Remember that the `contentType` is complementary to the target type. -It is a hint, which `MessageConverter` may or may not take into consideration. - -[[message-converters]] -==== Message Converters - -`MessageConverters` define two methods: - -[source, java] ----- -Object fromMessage(Message message, Class targetClass); - -Message toMessage(Object payload, @Nullable MessageHeaders headers); ----- - -It is important to understand the contract of these methods and their usage, specifically in the context of Spring Cloud Stream. - -The `fromMessage` method converts an incoming `Message` to an argument type. -The payload of the `Message` could be any type, and it is -up to the actual implementation of the `MessageConverter` to support multiple types. - - -[[provided-messageconverters]] -==== Provided MessageConverters - -As mentioned earlier, the framework already provides a stack of `MessageConverters` to handle most common use cases. -The following list describes the provided `MessageConverters`, in order of precedence (the first `MessageConverter` that works is used): - -. `JsonMessageConverter`: Supports conversion of the payload of the `Message` to/from POJO for cases when `contentType` is `application/json` using Jackson (DEFAULT) or Gson libraries. This message converter also aware of `type` parameter (e.g., _application/json;type=foo.bar.Person_). This is useful for cases where types may not be known at the time when function is developed, hence function signature may look like `Function` or `Function` or `Function`. In other words for type conversion we typically derive type from function signature. Having, mime-type parameter allows you to communicate type in a more dynamic way. -. `ByteArrayMessageConverter`: Supports conversion of the payload of the `Message` from `byte[]` to `byte[]` for cases when `contentType` is `application/octet-stream`. It is essentially a pass through and exists primarily for backward compatibility. -. `StringMessageConverter`: Supports conversion of any type to a `String` when `contentType` is `text/plain`. - -When no appropriate converter is found, the framework throws an exception. When that happens, you should check your code and configuration and ensure you did -not miss anything (that is, ensure that you provided a `contentType` by using a binding or a header). -However, most likely, you found some uncommon case (such as a custom `contentType` perhaps) and the current stack of provided `MessageConverters` -does not know how to convert. If that is the case, you can add custom `MessageConverter`. See <>. - -[[user-defined-message-converters]] -==== User-defined Message Converters - -Spring Cloud Function exposes a mechanism to define and register additional `MessageConverters`. -To use it, implement `org.springframework.messaging.converter.MessageConverter`, configure it as a `@Bean`. -It is then appended to the existing stack of `MessageConverter`s. - -NOTE: It is important to understand that custom `MessageConverter` implementations are added to the head of the existing stack. -Consequently, custom `MessageConverter` implementations take precedence over the existing ones, which lets you override as well as add to the existing converters. - -The following example shows how to create a message converter bean to support a new content type called `application/bar`: - -[source,java] ----- -@SpringBootApplication -public static class SinkApplication { - - ... - - @Bean - public MessageConverter customMessageConverter() { - return new MyCustomMessageConverter(); - } -} - -public class MyCustomMessageConverter extends AbstractMessageConverter { - - public MyCustomMessageConverter() { - super(new MimeType("application", "bar")); - } - - @Override - protected boolean supports(Class clazz) { - return (Bar.class.equals(clazz)); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, Object conversionHint) { - Object payload = message.getPayload(); - return (payload instanceof Bar ? payload : new Bar((byte[]) payload)); - } -} ----- - -[[note-on-json-options]] -==== Note on JSON options - -In Spring Cloud Function we support Jackson and Gson mechanisms to deal with JSON. -And for your benefit have abstracted it under `org.springframework.cloud.function.json.JsonMapper` which itself is aware of two mechanisms and will use the one selected -by you or following the default rule. -The default rules are as follows: - -* Whichever library is on the classpath that is the mechanism that is going to be used. So if you have `com.fasterxml.jackson.*` to the classpath, Jackson is going to be used and if you have `com.google.code.gson`, then Gson will be used. -* If you have both, then Gson will be the default, or you can set `spring.cloud.function.preferred-json-mapper` property with either of two values: `gson` or `jackson`. - - -That said, the type conversion is usually transparent to the developer, however given that `org.springframework.cloud.function.json.JsonMapper` is also registered as a bean -you can easily inject it into your code if needed. - - -[[kotlin-lambda-support]] -=== Kotlin Lambda support - -We also provide support for Kotlin lambdas (since v2.0). -Consider the following: - -[source, java] ----- -@Bean -open fun kotlinSupplier(): () -> String { - return { "Hello from Kotlin" } -} - -@Bean -open fun kotlinFunction(): (String) -> String { - return { it.toUpperCase() } -} - -@Bean -open fun kotlinConsumer(): (String) -> Unit { - return { println(it) } -} - ----- -The above represents Kotlin lambdas configured as Spring beans. The signature of each maps to a Java equivalent of -`Supplier`, `Function` and `Consumer`, and thus supported/recognized signatures by the framework. -While mechanics of Kotlin-to-Java mapping are outside of the scope of this documentation, it is important to understand that the -same rules for signature transformation outlined in "Java 8 function support" section are applied here as well. - -To enable Kotlin support all you need is to add Kotlin SDK libraries on the classpath which will trigger appropriate -autoconfiguration and supporting classes. - -[[function-component-scan]] -=== Function Component Scan - -Spring Cloud Function will scan for implementations of `Function`, `Consumer` and `Supplier` in a package called `functions` if it exists. Using this -feature you can write functions that have no dependencies on Spring - not even the `@Component` annotation is needed. If you want to use a different -package, you can set `spring.cloud.function.scan.packages`. You can also use `spring.cloud.function.scan.enabled=false` to switch off the scan completely. - -[[standalone-web-applications]] -== Standalone Web Applications - -Functions could be automatically exported as HTTP endpoints. - -The `spring-cloud-function-web` module has autoconfiguration that -activates when it is included in a Spring Boot web application (with -MVC support). There is also a `spring-cloud-starter-function-web` to -collect all the optional dependencies in case you just want a simple -getting started experience. - -With the web configurations activated your app will have an MVC -endpoint (on "/" by default, but configurable with -`spring.cloud.function.web.path`) that can be used to access the -functions in the application context where function name becomes part of the URL path. The supported content types are -plain text and JSON. - -IMPORTANT: It is important to understand that while SCF provides ability to export Functional beans as REST endpoints it is NOT a replacement for Spring MVC/WebFlux etc. -It is primarily to accommodate _stateless serverless patterns_ where you simply want to have some stateless functionality to be exposed via HTTP. - -|=== -| Method | Path | Request | Response | Status - -| GET | /{supplier} | - | Items from the named supplier | 200 OK -| POST | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted -| PUT | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted -| DELETE | /{consumer} | JSON object or text | - | 204 NO CONTENT -| POST | /{function} | JSON object or text | The result of applying the named function | 200 OK -| PUT | /{function} | JSON object or text | The result of applying the named function | 200 OK -| GET | /{function}/{item} | - | Convert the item into an object and return the result of applying the function | 200 OK - -|=== - -As the table above shows the behavior of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or `Flux`), then the response will also contain a single value. -For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream`. - -Functions and consumers that are declared with input and output in `Message` will see the request headers as _message headers_, and the output _message headers_ will be converted to HTTP headers. -The _payload_ of the Message will be a `body` or empty string if there is no `body` or it is null. - -When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accept headers for the best results). - -See <> to see the details and example on how to test such application. - -[[http-request-parameters]] -==== HTTP Request Parameters -As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., `/{function}/{item}`). -For example, `http://localhost:8080/uppercase/foo` will result in calling `uppercase` function with its input parameter being `foo`. - -While this is the recommended approach and the one that fits most use cases cases, there are times when you have to deal with HTTP request parameters (e.g., `http://localhost:8080/uppercase/foo?name=Bill`) -The framework will treat HTTP request parameters similar to the HTTP headers by storing them in the `Message` headers under the header key `http_request_param` -with its value being a `Map` of request parameters, so in order to access them your function input signature should accept `Message` type (e.g., `Function, String>`). For convenience we provide `HeaderUtils.HTTP_REQUEST_PARAM` constant. - -[[function-mapping-rules]] -=== Function Mapping rules - -If there is only a single function (consumer etc.) in the catalog, the name in the path is optional. -In other words, providing you only have `uppercase` function in catalog -`curl -H "Content-Type: text/plain" localhost:8080/uppercase -d hello` and `curl -H "Content-Type: text/plain" localhost:8080/ -d hello` calls are identical. - -Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line). -For example, `curl -H "Content-Type: text/plain" localhost:8080/uppercase,reverse -d hello`. - -For cases where there is more than a single function in catalog, each function will be exported and mapped with function name being -part of the path (e.g., `localhost:8080/uppercase`). -In this scenario you can still map specific function or function composition to the root path by providing -`spring.cloud.function.definition` property - -For example, ----- ---spring.cloud.function.definition=foo|bar ----- - -The above property will compose 'foo' and 'bar' function and map the composed function to the "/" path. - -The same property will also work for cases where function can not be resolved via URL. For example, your URL may be `localhost:8080/uppercase`, but there is no `uppercase` function. -However there are function `foo` and `bar`. So, in this case `localhost:8080/uppercase` will resolve to `foo|bar`. -This could be useful especially for cases when URL is used to communicate certain information since there will be Message header called `uri` with the value -of the actual URL, giving user ability to use it for evaluation and computation. - -[[function-filtering-rules]] -=== Function Filtering rules - -In situations where there are more than one function in catalog there may be a need to only export certain functions or function compositions. In that case you can use -the same `spring.cloud.function.definition` property listing functions you intend to export delimited by `;`. -Note that in this case nothing will be mapped to the root path and functions that are not listed (including compositions) are not going to be exported - -For example, - ----- ---spring.cloud.function.definition=foo;bar ----- - -This will only export function `foo` and function `bar` regardless how many functions are available in catalog (e.g., `localhost:8080/foo`). - ----- ---spring.cloud.function.definition=foo|bar;baz ----- - -This will only export function composition `foo|bar` and function `baz` regardless how many functions are available in catalog (e.g., `localhost:8080/foo,bar`). - -[[crud-rest-with-spring-cloud-function]] -=== CRUD REST with Spring Cloud Function - -By now it should be clear that functions are exported as REST endpoints and can be invoked using various HTTP methods. In other words a single -function could be triggered via GET, POST, PUT etc. - -However, it is not always desirable and certainly does not fit the CRUD concept. And while SCF does not support and has no intention of supporting -all the features of Spring web stack, the framework does provide support for CRUD mappings where a single function could be mapped to a particular HTTP method(s). -It is done via spring.cloud.function.http. property. - -For example, - ----- -spring.cloud.function.http.GET=uppercase;reverse;foo|bar -spring.cloud.function.http.POST=reverse -spring.cloud.function.http.DELETE=deleteById ----- - -As you can see, here we’re mapping functions to various HTTP methods using the same rules as `spring.cloud.function.definition` property where “;” allows us to define several functions and “|” signifies function composition. - -[[standalone-streaming-applications]] -== Standalone Streaming Applications - -To send or receive messages from a broker (such as RabbitMQ or Kafka) you can leverage `spring-cloud-stream` project and it's integration with Spring Cloud Function. -Please refer to https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/current/reference/html/spring-cloud-stream.html#spring_cloud_function[Spring Cloud Function] section of the https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] reference manual for more details and examples. - -[[deploying-a-packaged-function]] -== Deploying a Packaged Function - -Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the https://projectriff.io[Riff] Java function invoker uses this library). - -The standard entry point is to add `spring-cloud-function-deployer` to the classpath, the deployer kicks in and looks for some configuration to tell it where to find the function jar. - -```xml - - org.springframework.cloud - spring-cloud-function-deployer - ${spring.cloud.function.version} - -``` - - -At a minimum the user has to provide a `spring.cloud.function.location` which is a URL or resource location for the archive containing -the functions. It can optionally use a `maven:` prefix to locate the artifact via a dependency lookup (see `FunctionProperties` -for complete details). A Spring Boot application is bootstrapped from the jar file, using the `MANIFEST.MF` to locate a start class, so -that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function -registered in the main application's `FunctionCatalog`. The registered function can be applied by code in the main application, even though -it was created in an isolated class loader (by deault). - -Here is the example of deploying a JAR which contains an 'uppercase' function and invoking it . - -```java -@SpringBootApplication -public class DeployFunctionDemo { - - public static void main(String[] args) { - ApplicationContext context = SpringApplication.run(DeployFunctionDemo.class, - "--spring.cloud.function.location=..../target/uppercase-0.0.1-SNAPSHOT.jar", - "--spring.cloud.function.definition=uppercase"); - - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("uppercase"); - System.out.println(function.apply("hello")); - } -} -``` - -And here is the example using Maven URI (taken from one of the tests in `FunctionDeployerTests`): - -```java -@SpringBootApplication -public class DeployFunctionDemo { - - public static void main(String[] args) { - String[] args = new String[] { - "--spring.cloud.function.location=maven://oz.demo:demo-uppercase:0.0.1-SNAPSHOT", - "--spring.cloud.function.function-class=oz.demo.uppercase.MyFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("myFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - } -} -``` - -Keep in mind that Maven resource such as local and remote repositories, user, password and more are resolved using default MavenProperties which -effectively use local defaults and will work for majority of cases. However if you need to customize you can simply provide a bean of type -`MavenProperties` where you can set additional properties (see example below). - -```java -@Bean -public MavenProperties mavenProperties() { - MavenProperties properties = new MavenProperties(); - properties.setLocalRepository("target/it/"); - return properties; -} -``` - -[[supported-packaging-scenarios]] -=== Supported Packaging Scenarios - -Currently Spring Cloud Function supports several packaging scenarios to give you the most flexibility when it comes to deploying functions. - -[[simple-jar]] -==== Simple JAR - -This packaging option implies no dependency on anything related to Spring. -For example; Consider that such JAR contains the following class: -```java -package function.example; -. . . -public class UpperCaseFunction implements Function { - @Override - public String apply(String value) { - return value.toUpperCase(); - } -} -``` -All you need to do is specify `location` and `function-class` properties when deploying such package: - -``` ---spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar ---spring.cloud.function.function-class=function.example.UpperCaseFunction -``` - -It's conceivable in some cases that you might want to package multiple functions together. For such scenarios you can use -`spring.cloud.function.function-class` property to list several classes delimiting them by `;`. - -For example, - -``` ---spring.cloud.function.function-class=function.example.UpperCaseFunction;function.example.ReverseFunction -``` - -Here we are identifying two functions to deploy, which we can now access in function catalog by name (e.g., `catalog.lookup("reverseFunction");`). - - -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/simplestjar[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L70[FunctionDeployerTests]. - -*** Component Scanning *** - -Since version 3.1.4 you can simplify your configuration thru component scanning feature described in <>. If you place your functional class in -package named `functions`, you can omit `spring.cloud.function.function-class` property as framework will auto-discover functional classes loading them in function catalog. -Keep in mind the naming convention to follow when doing function lookup. For example function class `functions.UpperCaseFunction` will be available in `FunctionCatalog` -under the name `upperCaseFunction`. - -[[spring-boot-jar]] -==== Spring Boot JAR - -This packaging option implies there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR -runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. -For example; Consider that such JAR contains the following class (which could have some additional Spring dependencies providing Spring/Spring Boot is on the classpath): -```java -package function.example; -. . . -public class UpperCaseFunction implements Function { - @Override - public String apply(String value) { - return value.toUpperCase(); - } -} -``` -As before all you need to do is specify `location` and `function-class` properties when deploying such package: - -``` ---spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar ---spring.cloud.function.function-class=function.example.UpperCaseFunction -``` -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootjar[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L50[FunctionDeployerTests]. - -[[spring-boot-application]] -==== Spring Boot Application - -This packaging option implies your JAR is complete stand alone Spring Boot application with functions as managed Spring beans. -As before there is an obvious assumption that there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR -runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. -For example; Consider that such JAR contains the following class: -```java -package function.example; -. . . -@SpringBootApplication -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } -} -``` -Given that we're effectively dealing with another Spring Application context and that functions are spring managed beans, -in addition to the `location` property we also specify `definition` property instead of `function-class`. - -``` ---spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar ---spring.cloud.function.definition=uppercase -``` -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootapp[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L164[FunctionDeployerTests]. - -NOTE: This particular deployment option may or may not have Spring Cloud Function on it's classpath. From the deployer perspective this doesn't matter. - -[[functional-bean-definitions]] -== Functional Bean Definitions - -include::functional.adoc[leveloffset=+1] - -[[serverless-platform-adapters]] -== Serverless Platform Adapters - -As well as being able to run as a standalone process, a Spring Cloud -Function application can be adapted to run one of the existing -serverless platforms. In the project there are adapters for -https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS -Lambda], and https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure]. The https://github.com/fnproject/fn[Oracle Fn platform] has its own Spring Cloud Function adapter. And https://projectriff.io[Riff] supports Java functions and its -https://github.com/projectriff/java-function-invoker[Java Function Invoker] acts natively is an adapter for Spring Cloud Function jars. - -include::adapters/aws-intro.adoc[] -include::adapters/azure-intro.adoc[leveloffset=+1] -include::adapters/gcp-intro.adoc[] - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc b/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc new file mode 100644 index 000000000..a3b6ce4a1 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc @@ -0,0 +1,183 @@ +[[deploying-a-packaged-function]] += Deploying a Packaged Function + +Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the https://projectriff.io[Riff] Java function invoker uses this library). + +The standard entry point is to add `spring-cloud-function-deployer` to the classpath, the deployer kicks in and looks for some configuration to tell it where to find the function jar. + +```xml + + org.springframework.cloud + spring-cloud-function-deployer + ${spring.cloud.function.version} + +``` + + +At a minimum the user has to provide a `spring.cloud.function.location` which is a URL or resource location for the archive containing +the functions. It can optionally use a `maven:` prefix to locate the artifact via a dependency lookup (see `FunctionProperties` +for complete details). A Spring Boot application is bootstrapped from the jar file, using the `MANIFEST.MF` to locate a start class, so +that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function +registered in the main application's `FunctionCatalog`. The registered function can be applied by code in the main application, even though +it was created in an isolated class loader (by deault). + +Here is the example of deploying a JAR which contains an 'uppercase' function and invoking it . + +```java +@SpringBootApplication +public class DeployFunctionDemo { + + public static void main(String[] args) { + ApplicationContext context = SpringApplication.run(DeployFunctionDemo.class, + "--spring.cloud.function.location=..../target/uppercase-0.0.1-SNAPSHOT.jar", + "--spring.cloud.function.definition=uppercase"); + + FunctionCatalog catalog = context.getBean(FunctionCatalog.class); + Function function = catalog.lookup("uppercase"); + System.out.println(function.apply("hello")); + } +} +``` + +And here is the example using Maven URI (taken from one of the tests in `FunctionDeployerTests`): + +```java +@SpringBootApplication +public class DeployFunctionDemo { + + public static void main(String[] args) { + String[] args = new String[] { + "--spring.cloud.function.location=maven://oz.demo:demo-uppercase:0.0.1-SNAPSHOT", + "--spring.cloud.function.function-class=oz.demo.uppercase.MyFunction" }; + + ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); + FunctionCatalog catalog = context.getBean(FunctionCatalog.class); + Function function = catalog.lookup("myFunction"); + + assertThat(function.apply("bob")).isEqualTo("BOB"); + } +} +``` + +Keep in mind that Maven resource such as local and remote repositories, user, password and more are resolved using default MavenProperties which +effectively use local defaults and will work for majority of cases. However if you need to customize you can simply provide a bean of type +`MavenProperties` where you can set additional properties (see example below). + +```java +@Bean +public MavenProperties mavenProperties() { + MavenProperties properties = new MavenProperties(); + properties.setLocalRepository("target/it/"); + return properties; +} +``` + +[[supported-packaging-scenarios]] +== Supported Packaging Scenarios + +Currently Spring Cloud Function supports several packaging scenarios to give you the most flexibility when it comes to deploying functions. + +[[simple-jar]] +=== Simple JAR + +This packaging option implies no dependency on anything related to Spring. +For example; Consider that such JAR contains the following class: +```java +package function.example; +. . . +public class UpperCaseFunction implements Function { + @Override + public String apply(String value) { + return value.toUpperCase(); + } +} +``` +All you need to do is specify `location` and `function-class` properties when deploying such package: + +``` +--spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar +--spring.cloud.function.function-class=function.example.UpperCaseFunction +``` + +It's conceivable in some cases that you might want to package multiple functions together. For such scenarios you can use +`spring.cloud.function.function-class` property to list several classes delimiting them by `;`. + +For example, + +``` +--spring.cloud.function.function-class=function.example.UpperCaseFunction;function.example.ReverseFunction +``` + +Here we are identifying two functions to deploy, which we can now access in function catalog by name (e.g., `catalog.lookup("reverseFunction");`). + + +For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/simplestjar[here]. +You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L70[FunctionDeployerTests]. + +*** Component Scanning *** + +Since version 3.1.4 you can simplify your configuration thru component scanning feature described in <>. If you place your functional class in +package named `functions`, you can omit `spring.cloud.function.function-class` property as framework will auto-discover functional classes loading them in function catalog. +Keep in mind the naming convention to follow when doing function lookup. For example function class `functions.UpperCaseFunction` will be available in `FunctionCatalog` +under the name `upperCaseFunction`. + +[[spring-boot-jar]] +=== Spring Boot JAR + +This packaging option implies there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR +runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. +For example; Consider that such JAR contains the following class (which could have some additional Spring dependencies providing Spring/Spring Boot is on the classpath): +```java +package function.example; +. . . +public class UpperCaseFunction implements Function { + @Override + public String apply(String value) { + return value.toUpperCase(); + } +} +``` +As before all you need to do is specify `location` and `function-class` properties when deploying such package: + +``` +--spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar +--spring.cloud.function.function-class=function.example.UpperCaseFunction +``` +For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootjar[here]. +You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L50[FunctionDeployerTests]. + +[[spring-boot-application]] +=== Spring Boot Application + +This packaging option implies your JAR is complete stand alone Spring Boot application with functions as managed Spring beans. +As before there is an obvious assumption that there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR +runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. +For example; Consider that such JAR contains the following class: +```java +package function.example; +. . . +@SpringBootApplication +public class SimpleFunctionAppApplication { + + public static void main(String[] args) { + SpringApplication.run(SimpleFunctionAppApplication.class, args); + } + + @Bean + public Function uppercase() { + return value -> value.toUpperCase(); + } +} +``` +Given that we're effectively dealing with another Spring Application context and that functions are spring managed beans, +in addition to the `location` property we also specify `definition` property instead of `function-class`. + +``` +--spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar +--spring.cloud.function.definition=uppercase +``` +For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootapp[here]. +You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L164[FunctionDeployerTests]. + +NOTE: This particular deployment option may or may not have Spring Cloud Function on it's classpath. From the deployer perspective this doesn't matter. + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc b/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc new file mode 100644 index 000000000..69116d065 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc @@ -0,0 +1,5 @@ +[[functional-bean-definitions]] += Functional Bean Definitions + +include:../:functional.adoc[leveloffset=+1] + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc b/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc new file mode 100644 index 000000000..4fd7fa71e --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc @@ -0,0 +1,5 @@ +[[getting-started]] += Getting Started + +include:../:getting-started.adoc[] + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc b/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc new file mode 100644 index 000000000..9ae7af68c --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc @@ -0,0 +1,7 @@ +[[introduction]] += Introduction + +include:../:_intro.adoc[] + +include:../:https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing-docs.adoc[] + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc b/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc new file mode 100644 index 000000000..e602901aa --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc @@ -0,0 +1,717 @@ +[[programming-model]] += Programming model + +[[function.catalog]] + +[[function-catalog-and-flexible-function-signatures]] +== Function Catalog and Flexible Function Signatures + +One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions, +while providing a consistent execution model. +That's why all user defined functions are transformed into a canonical representation by `FunctionCatalog`. + +While users don't normally have to care about the `FunctionCatalog` at all, it is useful to know what +kind of functions are supported in user code. + +It is also important to understand that Spring Cloud Function provides first class support for reactive API +provided by https://projectreactor.io/[Project Reactor] allowing reactive primitives such as `Mono` and `Flux` +to be used as types in user defined functions providing greater flexibility when choosing programming model for +your function implementation. +Reactive programming model also enables functional support for features that would be otherwise difficult to impossible to implement +using imperative programming style. For more on this please read <> section. + +[[java-8-function-support]] +== Java 8 function support + +Spring Cloud Function embraces and builds on top of the 3 core functional interfaces defined by Java +and available to us since Java 8. + +- Supplier +- Function +- Consumer + +To avoid constantly mentioning `Supplier`, `Function` and `Consumer` we’ll refer to them a Functional beans for the rest of this manual where appropriate. + +In a nutshell, any bean in your Application Context that is Functional bean will lazily be registered with `FunctionCatalog`. +This means that it could benefit from all of the additional features described in this reference manual. + +In a simplest of application all you need to do is to declare `@Bean` of type `Supplier`, `Function` or `Consumer` in your application configuration. +Then you can access `FunctionCatalog` and lookup a particular function based on its name. + +For example: + + +[source, test] +---- +@Bean +public Function uppercase() { + return value -> value.toUpperCase(); +} + +. . . + +FunctionCatalog catalog = applicationContext.getBean(FunctionCatalog.class); +Function uppercase = catalog.lookup(“uppercase”); +---- + +Important to understand that given that `uppercase` is a bean, you can certainly get it form the `ApplicationContext` directly, but all you will get is just your bean as you declared it without any extra features provided by SCF. When you do lookup of a function via `FunctionCatalog`, the instance you will receive is wrapped (instrumented) with additional features (i.e., type conversion, composition etc.) described in this manual. Also, it is important to understand that a typical user does not use Spring Cloud Function directly. Instead a typical user implements Java `Function/Supplier/Consumer` with the idea of using it in different execution contexts without additional work. For example the same java function could be represented as _REST endpoint_ or _Streaming message handler_ or _AWS Lambda_ and more via Spring Cloud Function provided +adapters as well as other frameworks using Spring Cloud Function as the core programming model (e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]) +So in summary Spring Cloud Function instruments java functions with additional features to be utilised in variety of execution contexts. + + +[[function-definition]] +=== Function definition +While the previous example shows you how to lookup function in FunctionCatalog programmatically, in a typical integration case where Spring Cloud Function used as programming model by another framework (e.fg. Spring Cloud Stream), you declare which functions to use via `spring.cloud.function.definition` property. Knowing that it is important to understand some default behaviour when it comes to discovering functions in `FunctionCatalog`. For example, if you only have one Functional bean in your `ApplicationContext`, the `spring.cloud.function.definition` property typically will not be required, since a single function in `FunctionCatalog` can be looked up by an empty name or any name. For example, assuming that `uppercase` is the only function in your catalog, it can be looked up as `catalog.lookup(null)`, `catalog.lookup(“”)`, `catalog.lookup(“foo”)` +That said, for cases where you are using framework such as Spring Cloud Stream which uses `spring.cloud.function.definition` it is best practice and recommended to always use `spring.cloud.function.definition` property. + +For example, + +[source, test] +---- +spring.cloud.function.definition=uppercase +---- + +[[filtering-ineligible-functions]] +=== Filtering ineligible functions +A typical Application Context may include beans that are valid java functions, but not intended to be candidates to be registered with `FunctionCatalog`. +Such beans could be auto-configurations from other projects or any other beans that qualify to be Java functions. +The framework provides default filtering of known beans that should not be candidates for registration with function catalog. +You can also add to this list additional beans by providing coma delimited list of bean definition names using +`spring.cloud.function.ineligible-definitions` property. + +For example, + +[source, test] +---- +spring.cloud.function.ineligible-definitions=foo,bar +---- + +[[supplier]] +=== Supplier +Supplier can be _reactive_ - `Supplier>` +or _imperative_ - `Supplier`. From the invocation standpoint this should make no difference +to the implementor of such Supplier. However, when used within frameworks +(e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]), Suppliers, especially reactive, +often used to represent the source of the stream, therefore they are invoked once to get the stream (e.g., Flux) +to which consumers can subscribe to. In other words such suppliers represent an equivalent of an _infinite stream_. +However, the same reactive suppliers can also represent _finite_ stream(s) (e.g., result set on the polled JDBC data). +In those cases such reactive suppliers must be hooked up to some polling mechanism of the underlying framework. + +To assist with that Spring Cloud Function provides a marker annotation +`org.springframework.cloud.function.context.PollableBean` to signal that such supplier produces a +finite stream and may need to be polled again. That said, it is important to understand that Spring Cloud Function itself +provides no behavior for this annotation. + +In addition `PollableBean` annotation exposes a _splittable_ attribute to signal that produced stream +needs to be split (see https://www.enterpriseintegrationpatterns.com/patterns/messaging/Sequencer.html[Splitter EIP]) + +Here is the example: + +[source, java] +---- +@PollableBean(splittable = true) +public Supplier> someSupplier() { + return () -> { + String v1 = String.valueOf(System.nanoTime()); + String v2 = String.valueOf(System.nanoTime()); + String v3 = String.valueOf(System.nanoTime()); + return Flux.just(v1, v2, v3); + }; +} +---- + +[[function]] +=== Function +Function can also be written in imperative or reactive way, yet unlike Supplier and Consumer there are +no special considerations for the implementor other then understanding that when used within frameworks +such as https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] and others, reactive function is +invoked only once to pass a reference to the stream (Flux or Mono) and imperative is invoked once per event. + +[[consumer]] +=== Consumer +Consumer is a little bit special because it has a `void` return type, +which implies blocking, at least potentially. Most likely you will not +need to write `Consumer>`, but if you do need to do that, +remember to subscribe to the input flux. + +[[function-composition]] +== Function Composition +Function Composition is a feature that allows one to compose several functions into one. +The core support is based on function composition feature available with https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#andThen-java.util.function.Function-[Function.andThen(..)] +support available since Java 8. However on top of it, we provide few additional features. + +[[declarative-function-composition]] +=== Declarative Function Composition + +This feature allows you to provide composition instruction in a declarative way using `|` (pipe) or `,` (comma) delimiter +when providing `spring.cloud.function.definition` property. + +For example +---- +--spring.cloud.function.definition=uppercase|reverse +---- +Here we effectively provided a definition of a single function which itself is a composition of +function `uppercase` and function `reverse`. In fact that is one of the reasons why the property name is _definition_ and not _name_, +since the definition of a function can be a composition of several named functions. +And as mentioned you can use `,` instead of pipe (such as `...definition=uppercase,reverse`). + +[[composing-non-functions]] +=== Composing non-Functions +Spring Cloud Function also supports composing Supplier with `Consumer` or `Function` as well as `Function` with `Consumer`. +What's important here is to understand the end product of such definitions. +Composing Supplier with Function still results in Supplier while composing Supplier with Consumer will effectively render Runnable. +Following the same logic composing Function with Consumer will result in Consumer. + +And of course you can't compose uncomposable such as Consumer and Function, Consumer and Supplier etc. + + +[[function-routing-and-filtering]] +== Function Routing and Filtering + +Since version 2.2 Spring Cloud Function provides routing feature allowing +you to invoke a single function which acts as a router to an actual function you wish to invoke +This feature is very useful in certain FAAS environments where maintaining configurations +for several functions could be cumbersome or exposing more than one function is not possible. + +The `RoutingFunction` is registered in _FunctionCatalog_ under the name `functionRouter`. For simplicity +and consistency you can also refer to `RoutingFunction.FUNCTION_NAME` constant. + +This function has the following signature: + +[source, java] +---- +public class RoutingFunction implements Function { +. . . +} +---- +The routing instructions could be communicated in several ways. We support providing instructions via Message headers, System +properties as well as pluggable strategy. So let's look at some of the details + +[[messageroutingcallback]] +=== MessageRoutingCallback + +The `MessageRoutingCallback` is a strategy to assist with determining the name of the route-to function definition. + +[source, java] +---- +public interface MessageRoutingCallback { + FunctionRoutingResult routingResult(Message message); + . . . +} +---- + +All you need to do is implement and register it as a bean to be picked up by the `RoutingFunction`. +For example: + +[source, java] +---- +@Bean +public MessageRoutingCallback customRouter() { + return new MessageRoutingCallback() { + @Override + public FunctionRoutingResult routingResult(Message message) { + return new FunctionRoutingResult((String) message.getHeaders().get("func_name")); + } + }; +} +---- + +In the preceding example you can see a very simple implementation of `MessageRoutingCallback` which determines the function definition from +`func_name` Message header of the incoming Message and returns the instance of `FunctionRoutingResult` containing the definition of function to invoke. + +*Message Headers* + +If the input argument is of type `Message`, you can communicate routing instruction by setting one of +`spring.cloud.function.definition` or `spring.cloud.function.routing-expression` Message headers. +As the name of the property suggests `spring.cloud.function.routing-expression` relies on Spring Expression Language (SpEL). +For more static cases you can use `spring.cloud.function.definition` header which allows you to provide +the name of a single function (e.g., `...definition=foo`) or a composition instruction (e.g., `...definition=foo|bar|baz`). +For more dynamic cases you can use `spring.cloud.function.routing-expression` header and provide SpEL expression that should resolve +into definition of a function (as described above). + +NOTE: SpEL evaluation context's root object is the +actual input argument, so in the case of `Message` you can construct expression that has access +to both `payload` and `headers` (e.g., `spring.cloud.function.routing-expression=headers.function_name`). + +IMPORTANT: SpEL allows user to provide string representation of Java code to be executed. Given that the `spring.cloud.function.routing-expression` could be provided via Message headers means that ability to set such expression could be exposed to the end user (i.e., HTTP Headers when using web module) which could result in some problems (e.g., malicious code). To manage that, all expressions coming via Message headers will only be evaluated against `SimpleEvaluationContext` which has limited functionality and designed to only evaluate the context object (Message in our case). On the other hand, all expressions that are set via property or system variable are evaluated against `StandardEvaluationContext`, which allows for full flexibility of Java language. +While setting expression via system/application property or environment variable is generally considered to be secure as it is not exposed to the end user in normal cases, there are cases where visibility as well as capability to update system, application and environment variables are indeed exposed to the end user via Spring Boot Actuator endpoints provided either by some of the Spring projects or third parties or custom implementation by the end user. Such endpoints must be secured using industry standard web security practices. +Spring Cloud Function does not expose any of such endpoints. + +In specific execution environments/models the adapters are responsible to translate and communicate +`spring.cloud.function.definition` and/or `spring.cloud.function.routing-expression` via Message header. +For example, when using _spring-cloud-function-web_ you can provide `spring.cloud.function.definition` as an HTTP +header and the framework will propagate it as well as other HTTP headers as Message headers. + +*Application Properties* + +Routing instruction can also be communicated via `spring.cloud.function.definition` +or `spring.cloud.function.routing-expression` as application properties. The rules described in the +previous section apply here as well. The only difference is you provide these instructions as +application properties (e.g., `--spring.cloud.function.definition=foo`). + +NOTE: It is important to understand that providing `spring.cloud.function.definition` +or `spring.cloud.function.routing-expression` as Message headers will only work for imperative functions (e.g., `Function`). +That is to say that we can _only_ route ***per-message*** with imperative functions. With reactive functions we can not route +***per-message***. Therefore you can only provide your routing instructions as Application Properties. +It's all about unit-of-work. In imperative function unit of work is Message so we can route based on such unit-of-work. +With reactive function unit-of-work is the entire stream, so we'll act only on the instruction provided via application +properties and route the entire stream. + +*Order of priority for routing instructions* + +Given that we have several mechanisms of providing routing instructions it is important to understand the priorities for +conflict resolutions in the event multiple mechanisms are used at the same time, so here is the order: + +1. `MessageRoutingCallback` (If function is imperative will take over regardless if anything else is defined) +2. Message Headers (If function is imperative and no `MessageRoutingCallback` provided) +3. Application Properties (Any function) + +*Unroutable Messages* + +In the event route-to function is not available in catalog you will get an exception stating that. + +There are cases when such behavior is not desired and you may want to have some "catch-all" type function which can handle such messages. +To accomplish that, framework provides `org.springframework.cloud.function.context.DefaultMessageRoutingHandler` strategy. All you need to do is register it as a bean. +Its default implementation will simply log the fact that the message is un-routable, but will allow message flow to proceed without the exception, effectively dropping the un-routable message. +If you want something more sophisticated all you need to do is provide your own implementation of this strategy and register it as a bean. + +[source, java] +---- +@Bean +public DefaultMessageRoutingHandler defaultRoutingHandler() { + return new DefaultMessageRoutingHandler() { + @Override + public void accept(Message message) { + // do something really cool + } + }; +} +---- + +[[function-filtering]] +=== Function Filtering +Filtering is the type of routing where there are only two paths - 'go' or 'discard'. In terms of functions it mean +you only want to invoke a certain function if some condition returns 'true', otherwise you want to discard input. +However, when it comes to discarding input there are many interpretation of what it could mean in the context of your application. +For example, you may want to log it, or you may want to maintain the counter of discarded messages. you may also want to do nothing at all. +Because of these different paths, we do not provide a general configuration option for how to deal with discarded messages. +Instead we simply recommend to define a simple Consumer which would signify the 'discard' path: + +[source, java] +---- +@Bean +public Consumer devNull() { + // log, count or whatever +} +---- +Now you can have routing expression that really only has two paths effectively becoming a filter. For example: + +[source, text] +---- +--spring.cloud.function.routing-expression=headers.contentType.toString().equals('text/plain') ? 'echo' : 'devNull' +---- +Every message that does not fit criteria to go to 'echo' function will go to 'devNull' where you can simply do nothing with it. +The signature `Consumer` will also ensure that no type conversion will be attempted resulting in almost no execution overhead. + + +IMPORTANT: When dealing with reactive inputs (e.g., Publisher), routing instructions must only be provided via Function properties. This is +due to the nature of the reactive functions which are invoked only once to pass a Publisher and the rest +is handled by the reactor, hence we can not access and/or rely on the routing instructions communicated via individual +values (e.g., Message). + +[[multiple-routers]] +=== Multiple Routers + +By default the framework will always have a single routing function configured as described in previous sections. However, there are times when you may need more than one routing function. +In that case you can create your own instance of the `RoutingFunction` bean in addition to the existing one as long as you give it a name other than `functionRouter`. + +You can pass `spring.cloud.function.routing-expression` or `spring.cloud.function.definition` to RoutinFunction as key/value pairs in the map. + +Here is a simple example + +---- +@Configuration +protected static class MultipleRouterConfiguration { + + @Bean + RoutingFunction mySpecialRouter(FunctionCatalog functionCatalog, BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) { + Map propertiesMap = new HashMap<>(); + propertiesMap.put(FunctionProperties.PREFIX + ".routing-expression", "'reverse'"); + return new RoutingFunction(functionCatalog, propertiesMap, new BeanFactoryResolver(beanFactory), routingCallback); + } + + @Bean + public Function reverse() { + return v -> new StringBuilder(v).reverse().toString(); + } + + @Bean + public Function uppercase() { + return String::toUpperCase; + } +} +---- + +and a test that demonstrates how it works + +` +---- +@Test +public void testMultipleRouters() { + System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "'uppercase'"); + FunctionCatalog functionCatalog = this.configureCatalog(MultipleRouterConfiguration.class); + Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); + assertThat(function).isNotNull(); + Message message = MessageBuilder.withPayload("hello").build(); + assertThat(function.apply(message)).isEqualTo("HELLO"); + + function = functionCatalog.lookup("mySpecialRouter"); + assertThat(function).isNotNull(); + message = MessageBuilder.withPayload("hello").build(); + assertThat(function.apply(message)).isEqualTo("olleh"); +} +---- + +[[input/output-enrichment]] +== Input/Output Enrichment + +There are often times when you need to modify or refine an incoming or outgoing Message and to keep your code clean of non-functional concerns. You don’t want to do it inside of your business logic. + +You can always accomplish it via <>. Such approach provides several benefits: + +- It allows you to isolate this non-functional concern into a separate function which you can compose with the business function as function definition. +- It provides you with complete freedom (and danger) as to what you can modify before incoming message reaches the actual business function. + +[source, java] +---- +@Bean +public Function, Message> enrich() { + return message -> MessageBuilder.fromMessage(message).setHeader("foo", "bar").build(); +} + +@Bean +public Function, Message> myBusinessFunction() { + // do whatever +} +---- + +And then compose your function by providing the following function definition `enrich|myBusinessFunction`. + +While the described approach is the most flexible, it is also the most involved as it requires you to write some code, make it a bean or +manually register it as a function before you can compose it with the business function as you can see from the preceding example. + +But what if modifications (enrichments) you are trying to make are trivial as they are in the preceding example? Is there a simpler and more dynamic and configurable + mechanism to accomplish the same? + +Since version 3.1.3, the framework allows you to provide SpEL expression to enrich individual message headers for both input going into function and +and output coming out of it. Let’s look at one of the tests as the example. + +[source, java] +---- +@Test +public void testMixedInputOutputHeaderMapping() throws Exception { + try (ConfigurableApplicationContext context = new SpringApplicationBuilder( + SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( + "--logging.level.org.springframework.cloud.function=DEBUG", + "--spring.main.lazy-initialization=true", + "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut1='hello1'", + "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut2=headers.contentType", + "--spring.cloud.function.configuration.split.input-header-mapping-expression.key1=headers.path.split('/')[0]", + "--spring.cloud.function.configuration.split.input-header-mapping-expression.key2=headers.path.split('/')[1]", + "--spring.cloud.function.configuration.split.input-header-mapping-expression.key3=headers.path")) { + + FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); + FunctionInvocationWrapper function = functionCatalog.lookup("split"); + Message result = (Message) function.apply(MessageBuilder.withPayload("helo") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") + .setHeader("path", "foo/bar/baz").build()); + assertThat(result.getHeaders().containsKey("keyOut1")).isTrue(); + assertThat(result.getHeaders().get("keyOut1")).isEqualTo("hello1"); + assertThat(result.getHeaders().containsKey("keyOut2")).isTrue(); + assertThat(result.getHeaders().get("keyOut2")).isEqualTo("application/json"); + } +} +---- + +Here you see a properties called `input-header-mapping-expression` and `output-header-mapping-expression` preceded by the name of the function (i.e., `split`) and followed by the name of the message header key you want to set and the value as SpEL expression. The first expression (for 'keyOut1') is literal SpEL expressions enclosed in single quotes, effectively setting 'keyOut1' to value `hello1`. The `keyOut2` is set to the value of existing 'contentType' header. + +You can also observe some interesting features in the input header mapping where we actually splitting a value of the existing header 'path', setting individual values of key1 and key2 to the values of split elements based on the index. + +NOTE: if for whatever reason the provided expression evaluation fails, the execution of the function will proceed as if nothing ever happen. +However you will see the WARN message in your logs informing you about it + +[source, text] +---- +o.s.c.f.context.catalog.InputEnricher : Failed while evaluating expression "hello1" on incoming message. . . +---- + +In the event you are dealing with functions that have multiple inputs (next section), you can use index immediately after `input-header-mapping-expression` + +[source, text] +---- +--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1=‘hello1' +--spring.cloud.function.configuration.echo.input-header-mapping-expression[1].key2='hello2' +---- + +[[function-arity]] +== Function Arity + +There are times when a stream of data needs to be categorized and organized. For example, +consider a classic big-data use case of dealing with unorganized data containing, let’s say, +‘orders’ and ‘invoices’, and you want each to go into a separate data store. +This is where function arity (functions with multiple inputs and outputs) support +comes to play. + +Let’s look at an example of such a function (full implementation details are available +https://github.com/spring-cloud/spring-cloud-stream/blob/master/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/MultipleInputOutputFunctionTests.java#L342[here]), + +[source, java] +---- +@Bean +public Function, Tuple2, Flux>> organise() { + return flux -> ...; +} +---- + +Given that Project Reactor is a core dependency of SCF, we are using its Tuple library. +Tuples give us a unique advantage by communicating to us both _cardinality_ and _type_ information. +Both are extremely important in the context of SCSt. Cardinality lets us know +how many input and output bindings need to be created and bound to the corresponding +inputs and outputs of a function. Awareness of the type information ensures proper type +conversion. + +Also, this is where the ‘index’ part of the naming convention for binding +names comes into play, since, in this function, the two output binding +names are `organise-out-0` and `organise-out-1`. + +IMPORTANT: IMPORTANT: At the moment, function arity is *only* supported for reactive functions +(`Function...>, TupleN...>>`) centered on Complex event processing +where evaluation and computation on confluence of events typically requires view into a +stream of events rather than single event. + +[[input-header-propagation]] +== Input Header propagation + +In a typical scenario input Message headers are not propagated to output and rightfully so, since the output of a function may be an input to something else requiring it's own set of Message headers. +However, there are times when such propagation may be necessary so Spring Cloud Function provides several mechanisms to accomplish this. + +First you can always copy headers manually. For example, if you have a Function with the signature that takes `Message` and returns `Message` (i.e., `Function`), you can simply and selectively copy headers yourselves. Remember, if your function returns Message, the framework will not do anything to it other then properly converting its payload. +However, such approach may prove to be a bit tedious, especially in cases when you simply want to copy all headers. +To assist with cases like this we provide a simple property that would allow you to set a boolean flag on a function where you want input headers to be propagated. +The property is `copy-input-headers`. + +For example, let's assume you have the following configuration: + +[source, java] +---- +@EnableAutoConfiguration +@Configuration +protected static class InputHeaderPropagationConfiguration { + + @Bean + public Function uppercase() { + return x -> x.toUpperCase(); + } +} +---- + +As you know you can still invoke this function by sending a Message to it (framework will take care of type conversion and payload extraction) + +By simply setting `spring.cloud.function.configuration.uppercase.copy-input-headers` to `true`, the following assertion will be true as well + +---- +Function, Message> uppercase = catalog.lookup("uppercase", "application/json"); +Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHeader("foo", "bar").build()); +assertThat(result.getHeaders()).containsKey("foo"); +---- + +[[type-conversion-content-type-negotiation]] +== Type conversion (Content-Type negotiation) + +Content-Type negotiation is one of the core features of Spring Cloud Function as it allows to not only transform the incoming data to the types declared +by the function signature, but to do the same transformation during function composition making otherwise un-composable (by type) functions composable. + +To better understand the mechanics and the necessity behind content-type negotiation, we take a look at a very simple use case by +using the following function as an example: + +[source, java] +---- +@Bean +public Function personFunction {..} +---- + +The function shown in the preceding example expects a `Person` object as an argument and produces a String type as an output. If such function is +invoked with the type `Person`, than all works fine. But typically function plays a role of a handler for the incoming data which most often comes +in the raw format such as `byte[]`, `JSON String` etc. In order for the framework to succeed in passing the incoming data as an argument to +this function, it has to somehow transform the incoming data to a `Person` type. + +Spring Cloud Function relies on two native to Spring mechanisms to accomplish that. + +. _MessageConverter_ - to convert from incoming Message data to a type declared by the function. +. _ConversionService_ - to convert from incoming non-Message data to a type declared by the function. + +This means that depending on the type of the raw data (Message or non-Message) Spring Cloud Function will apply one or the other mechanisms. + +For most cases when dealing with functions that are invoked as part of some other request (e.g., HTTP, Messaging etc) the framework relies on `MessageConverters`, +since such requests already converted to Spring `Message`. In other words, the framework locates and applies the appropriate `MessageConverter`. +To accomplish that, the framework needs some instructions from the user. One of these instructions is already provided by the signature of the function +itself (Person type). Consequently, in theory, that should be (and, in some cases, is) enough. However, for the majority of use cases, in order to +select the appropriate `MessageConverter`, the framework needs an additional piece of information. That missing piece is `contentType` header. + +Such header usually comes as part of the Message where it is injected by the corresponding adapter that created such Message in the first place. +For example, HTTP POST request will have its content-type HTTP header copied to `contentType` header of the Message. + +For cases when such header does not exist framework relies on the default content type as `application/json`. + + +[[content-type-versus-argument-type]] +=== Content Type versus Argument Type + +As mentioned earlier, for the framework to select the appropriate `MessageConverter`, it requires argument type and, optionally, content type information. +The logic for selecting the appropriate `MessageConverter` resides with the argument resolvers which trigger right before the invocation of the user-defined +function (which is when the actual argument type is known to the framework). +If the argument type does not match the type of the current payload, the framework delegates to the stack of the +pre-configured `MessageConverters` to see if any one of them can convert the payload. + +The combination of `contentType` and argument type is the mechanism by which framework determines if message can be converted to a target type by locating +the appropriate `MessageConverter`. +If no appropriate `MessageConverter` is found, an exception is thrown, which you can handle by adding a custom `MessageConverter` +(see `<>`). + +NOTE: Do not expect `Message` to be converted into some other type based only on the `contentType`. +Remember that the `contentType` is complementary to the target type. +It is a hint, which `MessageConverter` may or may not take into consideration. + +[[message-converters]] +=== Message Converters + +`MessageConverters` define two methods: + +[source, java] +---- +Object fromMessage(Message message, Class targetClass); + +Message toMessage(Object payload, @Nullable MessageHeaders headers); +---- + +It is important to understand the contract of these methods and their usage, specifically in the context of Spring Cloud Stream. + +The `fromMessage` method converts an incoming `Message` to an argument type. +The payload of the `Message` could be any type, and it is +up to the actual implementation of the `MessageConverter` to support multiple types. + + +[[provided-messageconverters]] +=== Provided MessageConverters + +As mentioned earlier, the framework already provides a stack of `MessageConverters` to handle most common use cases. +The following list describes the provided `MessageConverters`, in order of precedence (the first `MessageConverter` that works is used): + +. `JsonMessageConverter`: Supports conversion of the payload of the `Message` to/from POJO for cases when `contentType` is `application/json` using Jackson (DEFAULT) or Gson libraries. This message converter also aware of `type` parameter (e.g., _application/json;type=foo.bar.Person_). This is useful for cases where types may not be known at the time when function is developed, hence function signature may look like `Function` or `Function` or `Function`. In other words for type conversion we typically derive type from function signature. Having, mime-type parameter allows you to communicate type in a more dynamic way. +. `ByteArrayMessageConverter`: Supports conversion of the payload of the `Message` from `byte[]` to `byte[]` for cases when `contentType` is `application/octet-stream`. It is essentially a pass through and exists primarily for backward compatibility. +. `StringMessageConverter`: Supports conversion of any type to a `String` when `contentType` is `text/plain`. + +When no appropriate converter is found, the framework throws an exception. When that happens, you should check your code and configuration and ensure you did +not miss anything (that is, ensure that you provided a `contentType` by using a binding or a header). +However, most likely, you found some uncommon case (such as a custom `contentType` perhaps) and the current stack of provided `MessageConverters` +does not know how to convert. If that is the case, you can add custom `MessageConverter`. See <>. + +[[user-defined-message-converters]] +=== User-defined Message Converters + +Spring Cloud Function exposes a mechanism to define and register additional `MessageConverters`. +To use it, implement `org.springframework.messaging.converter.MessageConverter`, configure it as a `@Bean`. +It is then appended to the existing stack of `MessageConverter`s. + +NOTE: It is important to understand that custom `MessageConverter` implementations are added to the head of the existing stack. +Consequently, custom `MessageConverter` implementations take precedence over the existing ones, which lets you override as well as add to the existing converters. + +The following example shows how to create a message converter bean to support a new content type called `application/bar`: + +[source,java] +---- +@SpringBootApplication +public static class SinkApplication { + + ... + + @Bean + public MessageConverter customMessageConverter() { + return new MyCustomMessageConverter(); + } +} + +public class MyCustomMessageConverter extends AbstractMessageConverter { + + public MyCustomMessageConverter() { + super(new MimeType("application", "bar")); + } + + @Override + protected boolean supports(Class clazz) { + return (Bar.class.equals(clazz)); + } + + @Override + protected Object convertFromInternal(Message message, Class targetClass, Object conversionHint) { + Object payload = message.getPayload(); + return (payload instanceof Bar ? payload : new Bar((byte[]) payload)); + } +} +---- + +[[note-on-json-options]] +=== Note on JSON options + +In Spring Cloud Function we support Jackson and Gson mechanisms to deal with JSON. +And for your benefit have abstracted it under `org.springframework.cloud.function.json.JsonMapper` which itself is aware of two mechanisms and will use the one selected +by you or following the default rule. +The default rules are as follows: + +* Whichever library is on the classpath that is the mechanism that is going to be used. So if you have `com.fasterxml.jackson.*` to the classpath, Jackson is going to be used and if you have `com.google.code.gson`, then Gson will be used. +* If you have both, then Gson will be the default, or you can set `spring.cloud.function.preferred-json-mapper` property with either of two values: `gson` or `jackson`. + + +That said, the type conversion is usually transparent to the developer, however given that `org.springframework.cloud.function.json.JsonMapper` is also registered as a bean +you can easily inject it into your code if needed. + + +[[kotlin-lambda-support]] +== Kotlin Lambda support + +We also provide support for Kotlin lambdas (since v2.0). +Consider the following: + +[source, java] +---- +@Bean +open fun kotlinSupplier(): () -> String { + return { "Hello from Kotlin" } +} + +@Bean +open fun kotlinFunction(): (String) -> String { + return { it.toUpperCase() } +} + +@Bean +open fun kotlinConsumer(): (String) -> Unit { + return { println(it) } +} + +---- +The above represents Kotlin lambdas configured as Spring beans. The signature of each maps to a Java equivalent of +`Supplier`, `Function` and `Consumer`, and thus supported/recognized signatures by the framework. +While mechanics of Kotlin-to-Java mapping are outside of the scope of this documentation, it is important to understand that the +same rules for signature transformation outlined in "Java 8 function support" section are applied here as well. + +To enable Kotlin support all you need is to add Kotlin SDK libraries on the classpath which will trigger appropriate +autoconfiguration and supporting classes. + +[[function-component-scan]] +== Function Component Scan + +Spring Cloud Function will scan for implementations of `Function`, `Consumer` and `Supplier` in a package called `functions` if it exists. Using this +feature you can write functions that have no dependencies on Spring - not even the `@Component` annotation is needed. If you want to use a different +package, you can set `spring.cloud.function.scan.packages`. You can also use `spring.cloud.function.scan.enabled=false` to switch off the scan completely. + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc b/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc new file mode 100644 index 000000000..9e2abf136 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc @@ -0,0 +1,14 @@ +[[serverless-platform-adapters]] += Serverless Platform Adapters + +As well as being able to run as a standalone process, a Spring Cloud +Function application can be adapted to run one of the existing +serverless platforms. In the project there are adapters for +https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS +Lambda], and https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure]. The https://github.com/fnproject/fn[Oracle Fn platform] has its own Spring Cloud Function adapter. And https://projectriff.io[Riff] supports Java functions and its +https://github.com/projectriff/java-function-invoker[Java Function Invoker] acts natively is an adapter for Spring Cloud Function jars. + +include:../:adapters/aws-intro.adoc[] +include:../:adapters/azure-intro.adoc[leveloffset=+1] +include:../:adapters/gcp-intro.adoc[] + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc b/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc new file mode 100644 index 000000000..e9898aec9 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc @@ -0,0 +1,6 @@ +[[standalone-streaming-applications]] += Standalone Streaming Applications + +To send or receive messages from a broker (such as RabbitMQ or Kafka) you can leverage `spring-cloud-stream` project and it's integration with Spring Cloud Function. +Please refer to https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/current/reference/html/spring-cloud-stream.html#spring_cloud_function[Spring Cloud Function] section of the https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] reference manual for more details and examples. + diff --git a/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc b/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc new file mode 100644 index 000000000..442989230 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc @@ -0,0 +1,120 @@ +[[standalone-web-applications]] += Standalone Web Applications + +Functions could be automatically exported as HTTP endpoints. + +The `spring-cloud-function-web` module has autoconfiguration that +activates when it is included in a Spring Boot web application (with +MVC support). There is also a `spring-cloud-starter-function-web` to +collect all the optional dependencies in case you just want a simple +getting started experience. + +With the web configurations activated your app will have an MVC +endpoint (on "/" by default, but configurable with +`spring.cloud.function.web.path`) that can be used to access the +functions in the application context where function name becomes part of the URL path. The supported content types are +plain text and JSON. + +IMPORTANT: It is important to understand that while SCF provides ability to export Functional beans as REST endpoints it is NOT a replacement for Spring MVC/WebFlux etc. +It is primarily to accommodate _stateless serverless patterns_ where you simply want to have some stateless functionality to be exposed via HTTP. + +|=== +| Method | Path | Request | Response | Status + +| GET | /{supplier} | - | Items from the named supplier | 200 OK +| POST | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted +| PUT | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted +| DELETE | /{consumer} | JSON object or text | - | 204 NO CONTENT +| POST | /{function} | JSON object or text | The result of applying the named function | 200 OK +| PUT | /{function} | JSON object or text | The result of applying the named function | 200 OK +| GET | /{function}/{item} | - | Convert the item into an object and return the result of applying the function | 200 OK + +|=== + +As the table above shows the behavior of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or `Flux`), then the response will also contain a single value. +For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream`. + +Functions and consumers that are declared with input and output in `Message` will see the request headers as _message headers_, and the output _message headers_ will be converted to HTTP headers. +The _payload_ of the Message will be a `body` or empty string if there is no `body` or it is null. + +When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accept headers for the best results). + +See <> to see the details and example on how to test such application. + +[[http-request-parameters]] +=== HTTP Request Parameters +As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., `/{function}/{item}`). +For example, `http://localhost:8080/uppercase/foo` will result in calling `uppercase` function with its input parameter being `foo`. + +While this is the recommended approach and the one that fits most use cases cases, there are times when you have to deal with HTTP request parameters (e.g., `http://localhost:8080/uppercase/foo?name=Bill`) +The framework will treat HTTP request parameters similar to the HTTP headers by storing them in the `Message` headers under the header key `http_request_param` +with its value being a `Map` of request parameters, so in order to access them your function input signature should accept `Message` type (e.g., `Function, String>`). For convenience we provide `HeaderUtils.HTTP_REQUEST_PARAM` constant. + +[[function-mapping-rules]] +== Function Mapping rules + +If there is only a single function (consumer etc.) in the catalog, the name in the path is optional. +In other words, providing you only have `uppercase` function in catalog +`curl -H "Content-Type: text/plain" localhost:8080/uppercase -d hello` and `curl -H "Content-Type: text/plain" localhost:8080/ -d hello` calls are identical. + +Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line). +For example, `curl -H "Content-Type: text/plain" localhost:8080/uppercase,reverse -d hello`. + +For cases where there is more than a single function in catalog, each function will be exported and mapped with function name being +part of the path (e.g., `localhost:8080/uppercase`). +In this scenario you can still map specific function or function composition to the root path by providing +`spring.cloud.function.definition` property + +For example, +---- +--spring.cloud.function.definition=foo|bar +---- + +The above property will compose 'foo' and 'bar' function and map the composed function to the "/" path. + +The same property will also work for cases where function can not be resolved via URL. For example, your URL may be `localhost:8080/uppercase`, but there is no `uppercase` function. +However there are function `foo` and `bar`. So, in this case `localhost:8080/uppercase` will resolve to `foo|bar`. +This could be useful especially for cases when URL is used to communicate certain information since there will be Message header called `uri` with the value +of the actual URL, giving user ability to use it for evaluation and computation. + +[[function-filtering-rules]] +== Function Filtering rules + +In situations where there are more than one function in catalog there may be a need to only export certain functions or function compositions. In that case you can use +the same `spring.cloud.function.definition` property listing functions you intend to export delimited by `;`. +Note that in this case nothing will be mapped to the root path and functions that are not listed (including compositions) are not going to be exported + +For example, + +---- +--spring.cloud.function.definition=foo;bar +---- + +This will only export function `foo` and function `bar` regardless how many functions are available in catalog (e.g., `localhost:8080/foo`). + +---- +--spring.cloud.function.definition=foo|bar;baz +---- + +This will only export function composition `foo|bar` and function `baz` regardless how many functions are available in catalog (e.g., `localhost:8080/foo,bar`). + +[[crud-rest-with-spring-cloud-function]] +== CRUD REST with Spring Cloud Function + +By now it should be clear that functions are exported as REST endpoints and can be invoked using various HTTP methods. In other words a single +function could be triggered via GET, POST, PUT etc. + +However, it is not always desirable and certainly does not fit the CRUD concept. And while SCF does not support and has no intention of supporting +all the features of Spring web stack, the framework does provide support for CRUD mappings where a single function could be mapped to a particular HTTP method(s). +It is done via spring.cloud.function.http. property. + +For example, + +---- +spring.cloud.function.http.GET=uppercase;reverse;foo|bar +spring.cloud.function.http.POST=reverse +spring.cloud.function.http.DELETE=deleteById +---- + +As you can see, here we’re mapping functions to various HTTP methods using the same rules as `spring.cloud.function.definition` property where “;” allows us to define several functions and “|” signifies function composition. + From 6c8cc870af4bcab01c24f37ad4868511a10ce3fc Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 06/31] Generate a default navigation --- docs/modules/ROOT/nav.adoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc new file mode 100644 index 000000000..057e94235 --- /dev/null +++ b/docs/modules/ROOT/nav.adoc @@ -0,0 +1,22 @@ +* xref:index.adoc[] +* xref:spring-integration.adoc[] +* xref:README.adoc[] +* xref:_intro.adoc[] +** xref:adapters/aws-intro.adoc[] +** xref:adapters/aws.adoc[] +** xref:adapters/azure-intro.adoc[] +** xref:adapters/azure.adoc[] +** xref:adapters/gcp-intro.adoc[] +** xref:adapters/gcp.adoc[] +* xref:functional.adoc[] +* xref:getting-started.adoc[] +* xref:sagan-index.adoc[] +* xref:spring-cloud-function.adoc[] +** xref:spring-cloud-function/introduction.adoc[] +** xref:spring-cloud-function/getting-started.adoc[] +** xref:spring-cloud-function/programming-model.adoc[] +** xref:spring-cloud-function/standalone-web-applications.adoc[] +** xref:spring-cloud-function/standalone-streaming-applications.adoc[] +** xref:spring-cloud-function/deploying-a-packaged.adoc[] +** xref:spring-cloud-function/functional-bean-definitions.adoc[] +** xref:spring-cloud-function/serverless-platform-adapters.adoc[] From 8dc27807d8a873423ad6bc8e8f638d4829346a39 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 07/31] Remove includes --- docs/modules/ROOT/pages/README.adoc | 2 -- docs/modules/ROOT/pages/adapters/aws.adoc | 1 - docs/modules/ROOT/pages/adapters/azure.adoc | 1 - docs/modules/ROOT/pages/adapters/gcp.adoc | 1 - 4 files changed, 5 deletions(-) diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc index 3db07e9f2..0c7de6ec8 100644 --- a/docs/modules/ROOT/pages/README.adoc +++ b/docs/modules/ROOT/pages/README.adoc @@ -5,12 +5,10 @@ image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={bran [[introduction]] = Introduction -include::_intro.adoc[] [[getting-started]] = Getting Started -include::getting-started.adoc[] [[building]] = Building diff --git a/docs/modules/ROOT/pages/adapters/aws.adoc b/docs/modules/ROOT/pages/adapters/aws.adoc index 77851da8e..271179d39 100644 --- a/docs/modules/ROOT/pages/adapters/aws.adoc +++ b/docs/modules/ROOT/pages/adapters/aws.adoc @@ -6,7 +6,6 @@ The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and c [[introduction]] = Introduction -include::adapters/aws-intro.adoc[] [[functional-bean-definitions]] = Functional Bean Definitions diff --git a/docs/modules/ROOT/pages/adapters/azure.adoc b/docs/modules/ROOT/pages/adapters/azure.adoc index 01dd586d4..490093572 100644 --- a/docs/modules/ROOT/pages/adapters/azure.adoc +++ b/docs/modules/ROOT/pages/adapters/azure.adoc @@ -1,3 +1,2 @@ *{project-version}* -include::adapters/azure-intro.adoc[] diff --git a/docs/modules/ROOT/pages/adapters/gcp.adoc b/docs/modules/ROOT/pages/adapters/gcp.adoc index 3b72f8bfe..490093572 100644 --- a/docs/modules/ROOT/pages/adapters/gcp.adoc +++ b/docs/modules/ROOT/pages/adapters/gcp.adoc @@ -1,3 +1,2 @@ *{project-version}* -include::adapters/gcp-intro.adoc[] From a22d344d2d621c95434ab69a24c28942075772ff Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 08/31] Fix cross references --- docs/modules/ROOT/pages/adapters/aws-intro.adoc | 2 +- .../modules/ROOT/pages/adapters/azure-intro.adoc | 16 ++++++++-------- docs/modules/ROOT/pages/index.adoc | 2 +- .../spring-cloud-function/programming-model.adoc | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/modules/ROOT/pages/adapters/aws-intro.adoc b/docs/modules/ROOT/pages/adapters/aws-intro.adoc index f9878866a..69d0cc782 100644 --- a/docs/modules/ROOT/pages/adapters/aws-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/aws-intro.adoc @@ -189,7 +189,7 @@ file: As pointed out in the <>, you will need a shaded jar in order to upload it to AWS Lambda. You can use the https://maven.apache.org/plugins/maven-shade-plugin/[Maven Shade Plugin] for that. -The example of the <> can be found above. +The example of the xref:adapters/aws-intro.adoc#shade-plugin-setup[setup] can be found above. You can use the Spring Boot Maven Plugin to generate the <>. [source,xml] diff --git a/docs/modules/ROOT/pages/adapters/azure-intro.adoc b/docs/modules/ROOT/pages/adapters/azure-intro.adoc index d357f5924..2a6394961 100644 --- a/docs/modules/ROOT/pages/adapters/azure-intro.adoc +++ b/docs/modules/ROOT/pages/adapters/azure-intro.adoc @@ -18,7 +18,7 @@ image::../images/scf-azure-adapter.svg[width=800,scaledwidth="75%",align="center TIP: For Web-based function applications, you can replace the generic `adapter-azure` with the specialized https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web[spring-cloud-function-adapter-azure-web]. With the Azure Web Adapter you can deploy any Spring Web application as an Azure, HttpTrigger, function. This adapter hides the Azure annotations complexity and uses the familiar https://docs.spring.io/spring-boot/docs/current/reference/html/web.html[Spring Web] programming model instead. -For further information follow the <> section below. +For further information follow the xref:adapters/azure-intro.adoc#azure.web.adapter[Azure Web Adapter] section below. [[azure-adapter]] = Azure Adapter @@ -58,7 +58,7 @@ NOTE: version `4.0.0+` is required. Having the adapter on the classpath activate == Development Guidelines Use the `@Component` (or `@Service`) annotation to turn any exiting Azure Function class (e.g. with `@FunctionName` handlers) into a Spring component. -Then you can auto-wire the required dependencies (or the <> for Spring Cloud Function composition) and use those inside the Azure function handlers. +Then you can auto-wire the required dependencies (or the xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] for Spring Cloud Function composition) and use those inside the Azure function handlers. [source,java] ---- @@ -99,7 +99,7 @@ When invoked by a trigger (such as `@HttpTrigger`), functions process that trigg <4> The `plainBean` method handler is mapped to an Azure function that uses of the auto-wired `uppercase` spring bean to compute the result. It demonstrates how to use "plain" Spring components in your Azure handlers. <5> The `springCloudFunction` method handler is mapped to another Azure function, that uses the auto-wired `FunctionCatalog` instance to compute the result. -<6> Shows how to leverage the Spring Cloud Function <> composition API. +<6> Shows how to leverage the Spring Cloud Function xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] composition API. TIP: Use the Java annotations included in the https://learn.microsoft.com/en-us/java/api/com.microsoft.azure.functions.annotation?view=azure-java-stable[com.microsoft.azure.functions.annotation.*] package to bind input and outputs to your methods. @@ -127,14 +127,14 @@ public class HttpTriggerDemoApplication { } } ---- -<1> The `@SpringBootApplication` annotated class is used as a `Main-Class` as explained in <>. +<1> The `@SpringBootApplication` annotated class is used as a `Main-Class` as explained in xref:adapters/azure-intro.adoc#star-class-configuration[main class configuration]. <2> Functions auto-wired and used in the Azure function handlers. [[function-catalog]] === Function Catalog The Spring Cloud Function supports a range of type signatures for user-defined functions, while providing a consistent execution model. -For this it uses the <> to transform all user defined functions into a canonical representation. +For this it uses the xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] to transform all user defined functions into a canonical representation. The Azure adapter can auto-wire any Spring component, such as the `uppercase` above. But those are treated as plain Java class instances, not as a canonical Spring Cloud Functions! @@ -189,7 +189,7 @@ To run your function applications on Microsoft Azure, you have to provide the ne Usually the Azure Maven (or Gradle) plugins are used to generate the necessary configurations from the annotated classes and to produce the required package format. IMPORTANT: The Azure https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#folder-structure[packaging format] is not compatible with the default Spring Boot packaging (e.g. `uber jar`). -The <> section below explains how to handle this. +The xref:adapters/azure-intro.adoc#disable.spring.boot.plugin[Disable Spring Boot Plugin] section below explains how to handle this. [[azure-maven/gradle-plugins]] === Azure Maven/Gradle Plugins @@ -300,7 +300,7 @@ You have to either disable the SpringBoot Maven/Gradle plugin or use the https:/ [[star-class-configuration]] === Main-Class Configuration -Specify the `Main-Class`/`Start-Class` to point to your Spring application entry point, such as the <> class in the example above. +Specify the `Main-Class`/`Start-Class` to point to your Spring application entry point, such as the xref:adapters/azure-intro.adoc#HttpTriggerDemoApplication[HttpTriggerDemoApplication] class in the example above. You can use the Maven `start-class` property or set the `Main-Class` attribute of your `MANIFEST/META-INFO`: @@ -394,7 +394,7 @@ dependencies { ---- ==== -The same <> and <> instructions apply to the `Azure Web Adapter` as well. +The same xref:adapters/azure-intro.adoc#azure.configuration[Configuration] and xref:adapters/azure-intro.adoc#azure.usage[Usage] instructions apply to the `Azure Web Adapter` as well. [[samples]] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index cc9d0d1dd..2cc3e7491 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -12,7 +12,7 @@ The reference documentation consists of the following sections: <> :: Spring Cloud Function Reference https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-cloudevent[Cloud Events] :: Cloud Events https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-rsocket[RSocket] :: RSocket -<<./spring-integration.adoc#spring-integration,Spring Integration>> :: Spring Integration Framework Interaction +xref:spring-integration.adoc[Spring Integration] :: Spring Integration Framework Interaction <> :: AWS Adapter Reference <> :: Azure Adapter Reference <> :: GCP Adapter Reference diff --git a/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc b/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc index e602901aa..7e00b2118 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc @@ -576,7 +576,7 @@ pre-configured `MessageConverters` to see if any one of them can convert the pay The combination of `contentType` and argument type is the mechanism by which framework determines if message can be converted to a target type by locating the appropriate `MessageConverter`. If no appropriate `MessageConverter` is found, an exception is thrown, which you can handle by adding a custom `MessageConverter` -(see `<>`). +(see `xref:spring-cloud-function/programming-model.adoc#user-defined-message-converters[User-defined Message Converters]`). NOTE: Do not expect `Message` to be converted into some other type based only on the `contentType`. Remember that the `contentType` is complementary to the target type. @@ -614,7 +614,7 @@ The following list describes the provided `MessageConverters`, in order of prece When no appropriate converter is found, the framework throws an exception. When that happens, you should check your code and configuration and ensure you did not miss anything (that is, ensure that you provided a `contentType` by using a binding or a header). However, most likely, you found some uncommon case (such as a custom `contentType` perhaps) and the current stack of provided `MessageConverters` -does not know how to convert. If that is the case, you can add custom `MessageConverter`. See <>. +does not know how to convert. If that is the case, you can add custom `MessageConverter`. See xref:spring-cloud-function/programming-model.adoc#user-defined-message-converters[User-defined Message Converters]. [[user-defined-message-converters]] === User-defined Message Converters From e19c2fec3be402afe91d3f91a19f00d7e6cc6f40 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:30 +0200 Subject: [PATCH 09/31] Enable Section Summary TOC for small pages --- docs/modules/ROOT/pages/README.adoc | 4 ++++ docs/modules/ROOT/pages/index.adoc | 1 + docs/modules/ROOT/pages/spring-cloud-function.adoc | 1 + .../spring-cloud-function/functional-bean-definitions.adoc | 1 + .../ROOT/pages/spring-cloud-function/getting-started.adoc | 1 + .../ROOT/pages/spring-cloud-function/introduction.adoc | 1 + .../spring-cloud-function/serverless-platform-adapters.adoc | 1 + .../standalone-streaming-applications.adoc | 1 + 8 files changed, 11 insertions(+) diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc index 0c7de6ec8..ca19eeae6 100644 --- a/docs/modules/ROOT/pages/README.adoc +++ b/docs/modules/ROOT/pages/README.adoc @@ -4,18 +4,22 @@ image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={bran [[introduction]] = Introduction +:page-section-summary-toc: 1 [[getting-started]] = Getting Started +:page-section-summary-toc: 1 [[building]] = Building +:page-section-summary-toc: 1 include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[] [[contributing]] = Contributing +:page-section-summary-toc: 1 include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 2cc3e7491..0594f9c27 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,5 +1,6 @@ [[spring-cloud-function-reference-documentation]] = Spring Cloud Function Reference Documentation +:page-section-summary-toc: 1 Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin, Chris Bono, Artem Bilan *{project-version}* diff --git a/docs/modules/ROOT/pages/spring-cloud-function.adoc b/docs/modules/ROOT/pages/spring-cloud-function.adoc index f44e47630..83270d240 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function.adoc @@ -1,5 +1,6 @@ [[spring-cloud-function]] = Spring Cloud Function +:page-section-summary-toc: 1 Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin diff --git a/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc b/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc index 69116d065..1eb88819a 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc @@ -1,5 +1,6 @@ [[functional-bean-definitions]] = Functional Bean Definitions +:page-section-summary-toc: 1 include:../:functional.adoc[leveloffset=+1] diff --git a/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc b/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc index 4fd7fa71e..8189dec01 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc @@ -1,5 +1,6 @@ [[getting-started]] = Getting Started +:page-section-summary-toc: 1 include:../:getting-started.adoc[] diff --git a/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc b/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc index 9ae7af68c..a5fa68562 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc @@ -1,5 +1,6 @@ [[introduction]] = Introduction +:page-section-summary-toc: 1 include:../:_intro.adoc[] diff --git a/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc b/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc index 9e2abf136..f6ff9b284 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc @@ -1,5 +1,6 @@ [[serverless-platform-adapters]] = Serverless Platform Adapters +:page-section-summary-toc: 1 As well as being able to run as a standalone process, a Spring Cloud Function application can be adapted to run one of the existing diff --git a/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc b/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc index e9898aec9..a50539b28 100644 --- a/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc @@ -1,5 +1,6 @@ [[standalone-streaming-applications]] = Standalone Streaming Applications +:page-section-summary-toc: 1 To send or receive messages from a broker (such as RabbitMQ or Kafka) you can leverage `spring-cloud-stream` project and it's integration with Spring Cloud Function. Please refer to https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/current/reference/html/spring-cloud-stream.html#spring_cloud_function[Spring Cloud Function] section of the https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] reference manual for more details and examples. From 19c60cf5ac8f5bca1553c08972314ddcdb57ff30 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 15:45:31 +0200 Subject: [PATCH 10/31] Initial commit --- .editorconfig | 14 - .github/ISSUE_TEMPLATE/bug_report.md | 17 - .github/ISSUE_TEMPLATE/feature_request.md | 20 - .github/workflows/deploy-docs.yml | 53 + .gitignore | 40 +- .mvn/jvm.config | 2 +- .mvn/maven.config | 1 - .mvn/settings.xml | 15 - .springformat | 0 .travis.yml | 11 - CONTRIBUTING.adoc | 3 - Guardfile | 12 - LICENSE | 202 -- README.adoc | 412 +--- SECURITY.md | 8 - ...antora-playbook.yml => antora-playbook.yml | 33 +- docs/.github/workflows/deploy-docs.yml | 32 - docs/antora.yml | 12 - .../modules/ROOT/assets/images/AWS-deploy.png | Bin 602969 -> 0 bytes docs/modules/ROOT/assets/images/remove.txt | 1 - .../ROOT/assets/images/scf-azure-adapter.svg | 272 --- docs/modules/ROOT/nav.adoc | 22 - docs/modules/ROOT/pages/README.adoc | 25 - docs/modules/ROOT/pages/_intro.adoc | 47 - .../ROOT/pages/adapters/aws-intro.adoc | 330 --- docs/modules/ROOT/pages/adapters/aws.adoc | 100 - .../ROOT/pages/adapters/azure-intro.adoc | 548 ----- docs/modules/ROOT/pages/adapters/azure.adoc | 2 - .../ROOT/pages/adapters/gcp-intro.adoc | 304 --- docs/modules/ROOT/pages/adapters/gcp.adoc | 2 - docs/modules/ROOT/pages/functional.adoc | 321 --- docs/modules/ROOT/pages/getting-started.adoc | 33 - docs/modules/ROOT/pages/index.adoc | 25 - docs/modules/ROOT/pages/sagan-index.adoc | 46 - .../ROOT/pages/spring-cloud-function.adoc | 16 - .../deploying-a-packaged.adoc | 183 -- .../functional-bean-definitions.adoc | 6 - .../getting-started.adoc | 6 - .../spring-cloud-function/introduction.adoc | 8 - .../programming-model.adoc | 717 ------- .../serverless-platform-adapters.adoc | 15 - .../standalone-streaming-applications.adoc | 7 - .../standalone-web-applications.adoc | 120 -- .../ROOT/pages/spring-integration.adoc | 101 - docs/pom.xml | 68 - docs/src/main/asciidoc/ghpages.sh | 330 --- docs/src/main/asciidoc/images/AWS-deploy.png | Bin 602969 -> 0 bytes docs/src/main/asciidoc/images/remove.txt | 1 - .../asciidoc/images/scf-azure-adapter.svg | 272 --- docs/src/main/images/ce.png | Bin 51852 -> 0 bytes docs/src/main/images/message.png | Bin 45929 -> 0 bytes docs/src/main/ruby/generate_readme.sh | 37 - pipeline.yml | 76 - pom.xml | 241 +-- spring-cloud-function-adapters/pom.xml | 29 - .../README.adoc | 7 - .../spring-cloud-function-adapter-aws/pom.xml | 162 -- .../aws/AWSCompanionAutoConfiguration.java | 43 - .../function/adapter/aws/AWSLambdaUtils.java | 253 --- .../adapter/aws/AWSTypesMessageConverter.java | 120 -- .../adapter/aws/CustomRuntimeEventLoop.java | 279 --- .../adapter/aws/CustomRuntimeInitializer.java | 77 - .../function/adapter/aws/FunctionInvoker.java | 158 -- .../aws/LambdaDestinationResolver.java | 59 - .../adapter/test/aws/AWSCustomRuntime.java | 98 - .../main/resources/META-INF/spring.factories | 2 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../aws/CustomRuntimeEventLoopTest.java | 297 --- .../adapter/aws/FunctionInvokerTests.java | 1830 ----------------- .../function/adapter/aws/TestContext.java | 97 - .../README.adoc | 11 - .../pom.xml | 75 - .../azure/web/AzureWebProxyInvoker.java | 144 -- ...ctions.spi.inject.FunctionInstanceInjector | 1 - .../src/main/resources/application.properties | 1 - .../spring-azure-function-banner.txt | 8 - .../azure/web/AzureWebProxyInvokerTests.java | 181 -- .../cloud/function/adapter/azure/web/Pet.java | 58 - .../function/adapter/azure/web/PetData.java | 118 -- .../azure/web/PetStoreSpringAppConfig.java | 68 - .../adapter/azure/web/PetsController.java | 76 - .../azure/web/TestExecutionContext.java | 47 - .../spring-cloud-function-adapter-azure/.jdk8 | 0 .../README.adoc | 17 - .../pom.xml | 110 - .../azure/AzureFunctionInstanceInjector.java | 105 - .../adapter/azure/AzureFunctionUtil.java | 118 -- .../adapter/azure/FunctionInvoker.java | 390 ---- .../adapter/azure/HttpFunctionInvoker.java | 47 - ...ctions.spi.inject.FunctionInstanceInjector | 1 - .../spring-azure-function-banner.txt | 8 - .../azure/CustomFunctionInvokerTests.java | 201 -- .../adapter/azure/FunctionInvokerTests.java | 369 ---- .../azure/HttpFunctionInvokerTests.java | 160 -- .../adapter/azure/helper/BuilderStub.java | 55 - .../azure/helper/HttpRequestMessageStub.java | 91 - .../azure/helper/HttpResponseMessageStub.java | 53 - .../azure/helper/TestExecutionContext.java | 47 - .../AzureFunctionInstanceInjectorTest.java | 112 - ...ionInstanceInjectorServiceLoadingTest.java | 134 -- .../src/test/resources/log4j.xml | 13 - .../spring-cloud-function-adapter-gcp/pom.xml | 74 - .../function/adapter/gcp/FunctionInvoker.java | 226 -- .../function/adapter/gcp/GcfJarLauncher.java | 62 - .../adapter/gcp/layout/GcfJarLayout.java | 55 - .../gcp/layout/GcfJarLayoutFactory.java | 36 - .../main/resources/META-INF/spring.factories | 2 - .../cloud/function/adapter/gcp/Context.java | 69 - .../gcp/FunctionInvokerBackgroundTests.java | 289 --- .../adapter/gcp/FunctionInvokerHttpTests.java | 307 --- .../function/adapter/gcp/PubSubMessage.java | 70 - .../FunctionInvokerIntegrationTests.java | 163 -- .../integration/LocalServerTestSupport.java | 171 -- .../.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.md | 40 - .../mvnw | 310 --- .../mvnw.cmd | 182 -- .../pom.xml | 108 - .../ce/CloudEventGrpcAutoConfiguration.java | 47 - .../function/grpc/ce/CloudEventHandler.java | 54 - .../grpc/ce/CloudEventMessageConverter.java | 101 - .../src/main/proto/CloudEvent.proto | 49 - .../src/main/proto/CloudEventService.proto | 17 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../src/main/resources/application.properties | 1 - ...unctionGrpcCloudeventApplicationTests.java | 28 - .../spring-cloud-function-grpc/.jdk8 | 0 .../spring-cloud-function-grpc/README.md | 233 --- .../spring-cloud-function-grpc/pom.xml | 102 - .../grpc/AbstractGrpcMessageConverter.java | 61 - .../function/grpc/FunctionGrpcProperties.java | 74 - .../function/grpc/GrpcAutoConfiguration.java | 75 - .../function/grpc/GrpcClientTemplate.java | 5 - .../function/grpc/GrpcMessageConverter.java | 34 - .../cloud/function/grpc/GrpcServer.java | 111 - .../grpc/GrpcServerMessageHandler.java | 110 - .../grpc/GrpcSpringMessageConverter.java | 59 - .../cloud/function/grpc/GrpcUtils.java | 309 --- .../function/grpc/MessageHandlingHelper.java | 380 ---- .../src/main/proto/MessageService.proto | 18 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../function/grpc/GrpcInteractionTests.java | 366 ---- .../src/test/resources/application.properties | 1 - .../.jdk8 | 0 .../README.md | 14 - .../pom.xml | 54 - .../sample/pet-store/.aws-sam/build.toml | 13 - .../sample/pet-store/README.md | 38 - .../sample/pet-store/pom.xml | 192 -- .../sample/pet-store/src/assembly/bin.xml | 24 - .../petstore/PetStoreSpringAppConfig.java | 71 - .../oz/spring/petstore/PetsController.java | 80 - .../java/oz/spring/petstore/model/Error.java | 33 - .../java/oz/spring/petstore/model/Pet.java | 58 - .../oz/spring/petstore/model/PetData.java | 115 -- .../sample/pet-store/template.yml | 37 - .../serverless/web/FunctionClassUtils.java | 145 -- .../serverless/web/ProxyAsyncContext.java | 176 -- .../serverless/web/ProxyErrorController.java | 81 - .../web/ProxyFilterRegistration.java | 115 -- .../web/ProxyHttpServletRequest.java | 1013 --------- .../web/ProxyHttpServletResponse.java | 483 ----- .../serverless/web/ProxyHttpSession.java | 112 - .../function/serverless/web/ProxyMvc.java | 340 --- .../serverless/web/ProxyServletContext.java | 355 ---- .../web/ProxyServletRegistration.java | 143 -- .../web/ServerlessWebApplication.java | 402 ---- .../serverless/web/RequestResponseTests.java | 155 -- .../cloud/function/test/app/Pet.java | 58 - .../cloud/function/test/app/PetData.java | 118 -- .../test/app/PetStoreSpringAppConfig.java | 108 - .../function/test/app/PetsController.java | 111 - spring-cloud-function-context/pom.xml | 199 -- .../function/actuator/FunctionsEndpoint.java | 81 - .../cloudevent/CloudEventHeaderEnricher.java | 59 - .../cloudevent/CloudEventMessageBuilder.java | 213 -- .../cloudevent/CloudEventMessageUtils.java | 450 ---- ...dEventsFunctionExtensionConfiguration.java | 42 - .../CloudEventsFunctionInvocationHelper.java | 157 -- .../context/DefaultMessageRoutingHandler.java | 51 - .../function/context/FunctionCatalog.java | 100 - .../function/context/FunctionProperties.java | 232 --- .../context/FunctionRegistration.java | 201 -- .../function/context/FunctionRegistry.java | 27 - .../context/FunctionTypeProcessor.java | 111 - .../context/FunctionalSpringApplication.java | 192 -- .../context/MessageRoutingCallback.java | 50 - .../cloud/function/context/PollableBean.java | 63 - .../context/PostProcessingFunction.java | 62 - .../BeanFactoryAwareFunctionRegistry.java | 294 --- .../catalog/FunctionAroundWrapper.java | 55 - .../context/catalog/FunctionCatalogEvent.java | 32 - .../catalog/FunctionRegistrationEvent.java | 47 - .../context/catalog/FunctionTypeUtils.java | 563 ----- .../catalog/FunctionUnregistrationEvent.java | 47 - .../context/catalog/HeaderEnricher.java | 92 - .../catalog/SimpleFunctionRegistry.java | 1537 -------------- ...ntextFunctionCatalogAutoConfiguration.java | 225 -- .../ContextFunctionCatalogInitializer.java | 266 --- .../context/config/FunctionContextUtils.java | 130 -- .../FunctionsEndpointAutoConfiguration.java | 46 - .../context/config/JsonMessageConverter.java | 162 -- ...tlinLambdaToFunctionAutoConfiguration.java | 261 --- .../context/config/RoutingFunction.java | 244 --- .../SmartCompositeMessageConverter.java | 200 -- .../context/message/MessageUtils.java | 74 - .../test/FunctionalSpringBootTest.java | 57 - .../test/FunctionalTestContextLoader.java | 38 - .../cloud/function/json/GsonMapper.java | 70 - .../cloud/function/json/JacksonMapper.java | 96 - .../cloud/function/json/JsonMapper.java | 142 -- .../DefaultFunctionObservationConvention.java | 48 - .../observability/FunctionContext.java | 46 - .../observability/FunctionObservation.java | 63 - .../FunctionObservationConvention.java | 35 - .../ObservationAutoConfiguration.java | 43 - .../ObservationFunctionAroundWrapper.java | 56 - .../function/utils/FunctionClassUtils.java | 153 -- .../function/utils/FunctionMessageUtils.java | 69 - ...mitiveTypesFromStringMessageConverter.java | 59 - .../cloud/function/utils/SocketUtils.java | 38 - .../context/config/CoroutinesUtils.kt | 132 -- .../spring-configuration-metadata.json | 24 - .../main/resources/META-INF/spring.factories | 4 - .../resources/META-INF/spring/aot.factories | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 5 - .../cloudevent/CloudEventFunctionTests.java | 415 ---- ...CloudEventMessageUtilsAndBuilderTests.java | 141 -- .../cloudevent/SpringReleaseEvent.java | 67 - .../function/context/HeaderMappingTests.java | 264 --- .../HybridFunctionalRegistrationTests.java | 126 -- .../context/MessageRoutingCallbackTests.java | 148 -- ...yAwareFunctionRegistryMultiInOutTests.java | 487 ----- ...BeanFactoryAwareFunctionRegistryTests.java | 1436 ------------- ...FactoryAwarePojoFunctionRegistryTests.java | 141 -- .../catalog/FunctionTypeUtilsTests.java | 208 -- .../catalog/SimpleFunctionRegistryTests.java | 839 -------- ...oConfigurationConditionalLoadingTests.java | 102 - ...FunctionCatalogAutoConfigurationTests.java | 911 -------- ...ontextFunctionCatalogInitializerTests.java | 428 ---- .../config/JsonMessageConverterTests.java | 70 - .../context/config/RoutingFunctionTests.java | 331 --- .../function/context/scan/TestFunction.java | 32 - .../string/FunctionalStringSourceTests.java | 60 - .../context/test/FunctionalTests.java | 57 - .../function/inject/FooConfiguration.java | 33 - .../cloud/function/scan/ScannedFunction.java | 39 - .../cloud/function/test/GenericFunction.java | 39 - .../function/userissues/UserIssuesTests.java | 159 -- .../cloud/function/utils/JsonMapperTests.java | 143 -- .../src/test/resources/avro/sensor.avsc | 11 - .../src/test/resources/greeter.jar | Bin 1015 -> 0 bytes spring-cloud-function-core/.jdk8 | 0 spring-cloud-function-core/pom.xml | 34 - .../core/FunctionInvocationHelper.java | 40 - spring-cloud-function-dependencies/pom.xml | 138 -- spring-cloud-function-deployer/.gitignore | 31 - .../.mvn/wrapper/MavenWrapperDownloader.java | 114 - .../.mvn/wrapper/maven-wrapper.jar | Bin 48337 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 - .../demo-stream-0.0.1-SNAPSHOT.jar | Bin 4086 -> 0 bytes .../demo-stream-0.0.1-SNAPSHOT.pom | 107 - .../0.0.1-SNAPSHOT/maven-metadata-local.xml | 24 - .../demo/demo-stream/maven-metadata-local.xml | 11 - spring-cloud-function-deployer/mvnw | 286 --- spring-cloud-function-deployer/mvnw.cmd | 161 -- spring-cloud-function-deployer/pom.xml | 152 -- .../src/it/bootapp-multi/pom.xml | 105 - .../src/main/java/function/example/MyFn.java | 29 - .../function/example/RepeaterApplication.java | 80 - .../src/it/bootapp-with-javax/pom.xml | 105 - .../example/SimpleFunctionAppApplication.java | 57 - .../function/example/UpperCaseFunction.java | 23 - .../src/it/bootapp-with-scf/pom.xml | 105 - .../example/SimpleFunctionAppApplication.java | 63 - .../function/example/UpperCaseFunction.java | 13 - .../src/it/bootapp/pom.xml | 100 - .../example/SimpleFunctionAppApplication.java | 57 - .../function/example/UpperCaseFunction.java | 13 - .../src/it/bootjar-multi/pom.xml | 106 - .../main/java/function/example/Repeater.java | 27 - .../src/it/bootjar/pom.xml | 100 - .../function/example/ReverseFunction.java | 13 - .../example/SimpleFunctionAppApplication.java | 15 - .../function/example/UpperCaseFunction.java | 13 - .../src/it/bootjarnostart/pom.xml | 112 - .../function/example/UpperCaseFunction.java | 13 - .../src/it/settings.xml | 35 - .../src/it/simplestjar/pom.xml | 54 - .../example/EchoCloudEventFunction.java | 16 - .../src/it/simplestjarcs/pom.xml | 33 - .../java/functions/UpperCaseFunction.java | 13 - .../deployer/DeployerContextUtils.java | 121 -- .../deployer/FunctionArchiveDeployer.java | 337 --- .../FunctionDeployerConfiguration.java | 187 -- .../deployer/FunctionDeployerProperties.java | 69 - .../main/resources/META-INF/spring.factories | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../deployer/FunctionDeployerTests.java | 439 ---- spring-cloud-function-integration/pom.xml | 41 - .../dsl/FunctionFlowAutoConfiguration.java | 40 - .../integration/dsl/FunctionFlowBuilder.java | 172 -- .../dsl/FunctionFlowDefinition.java | 94 - .../integration/dsl/FunctionLookupHelper.java | 90 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../integration/dsl/FunctionFlowTests.java | 182 -- spring-cloud-function-kotlin/.jdk8 | 0 spring-cloud-function-kotlin/README.adoc | 4 - spring-cloud-function-kotlin/pom.xml | 137 -- .../main/resources/META-INF/spring.factories | 0 ...ogAutoConfigurationKotlinSuspendTests.java | 77 - ...onCatalogAutoConfigurationKotlinTests.java | 173 -- .../function/kotlin/ComponentUppercase.kt | 10 - .../kotlin/KotlinComponentFunction.kt | 12 - .../kotlin/KotlinLambdasConfiguration.kt | 67 - .../KotlinSuspendFlowLambdasConfiguration.kt | 64 - .../KotlinSuspendLambdasConfiguration.kt | 46 - .../cloud/function/kotlin/Person.kt | 33 - .../kotlin/aws/AwsKotlinTestsTests.kt | 84 - .../aws/KotlinAwsLambdasConfiguration.kt | 43 - .../web/HeadersToMessageSuspendTests.kt | 108 - .../kotlin/web/HeadersToMessageTests.kt | 103 - spring-cloud-function-rsocket/.jdk8 | 0 spring-cloud-function-rsocket/NOTES.txt | 7 - spring-cloud-function-rsocket/README.md | 99 - spring-cloud-function-rsocket/pom.xml | 68 - .../FunctionRSocketMessageHandler.java | 311 --- .../rsocket/FunctionRSocketUtils.java | 137 -- .../rsocket/MessageAwareJsonDecoder.java | 171 -- .../rsocket/MessageAwareJsonEncoder.java | 114 - .../rsocket/RSocketAutoConfiguration.java | 58 - .../RSocketCustomizerConfiguration.java | 51 - .../rsocket/RSocketForwardingFunction.java | 77 - .../rsocket/RSocketFunctionProperties.java | 42 - .../rsocket/RSocketListenerFunction.java | 149 -- .../RSocketRoutingAutoConfiguration.java | 50 - .../main/resources/META-INF/spring.factories | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 2 - .../MessageRoutingCallbackRSocketTests.java | 143 -- .../function/rsocket/MessagingTests.java | 401 ---- .../RSocketAutoConfigurationRoutingTests.java | 231 --- .../RSocketAutoConfigurationTests.java | 728 ------- .../function/rsocket/RoutingBrokerTests.java | 144 -- .../function/rsocket/TestSocketUtils.java | 75 - .../src/test/resources/application.properties | 2 - .../function-functional-sample-aws/.jdk8 | 0 .../build.gradle | 93 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-functional-sample-aws/gradlew | 164 -- .../gradlew.bat | 90 - .../function-functional-sample-aws/pom.xml | 140 -- .../java/example/FunctionConfiguration.java | 37 - .../src/main/java/example/TestFunction.java | 13 - .../src/main/resources/application.properties | 1 - .../src/main/resources/log4j.properties | 20 - .../src/test/java/example/MapTests.java | 31 - .../README.adoc | 12 - .../function-sample-aws-custom-bean/pom.xml | 142 -- .../src/assembly/zip.xml | 35 - .../java/com/example/LambdaApplication.java | 71 - .../src/main/resources/application.properties | 2 - .../src/main/resources/bootstrap | 8 - .../src/test/resources/testBootstrap | 6 - .../function-sample-aws-custom/README.adoc | 11 - .../function-sample-aws-custom/pom.xml | 192 -- .../src/assembly/zip.xml | 35 - .../java/com/example/LambdaApplication.java | 40 - .../src/main/resources/application.properties | 4 - .../src/main/resources/bootstrap | 8 - .../com/example/LambdaApplicationTests.java | 45 - .../src/test/resources/testBootstrap | 6 - .../function-sample-aws-native/.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.jar | Bin 58727 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../function-sample-aws-native/Dockerfile | 43 - .../function-sample-aws-native/README.md | 44 - .../function-sample-aws-native/mvnw | 316 --- .../function-sample-aws-native/mvnw.cmd | 188 -- .../function-sample-aws-native/pom.xml | 187 -- .../src/assembly/java.xml | 31 - .../src/assembly/native.xml | 29 - .../demo/NativeUppercaseApplication.java | 50 - .../src/main/resources/application.properties | 1 - .../src/shell/java/bootstrap | 7 - .../src/shell/native/bootstrap | 5 - .../demo/NativeUppercaseApplicationTests.java | 13 - .../function-sample-aws-routing/.jdk8 | 0 .../function-sample-aws-routing/README.adoc | 34 - .../function-sample-aws-routing/build.gradle | 93 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-sample-aws-routing/gradlew | 164 -- .../function-sample-aws-routing/gradlew.bat | 90 - .../function-sample-aws-routing/pom.xml | 145 -- .../java/example/FunctionConfiguration.java | 29 - .../src/main/resources/application.properties | 1 - .../src/main/resources/log4j.properties | 20 - .../src/test/java/example/MapTests.java | 31 - .../function-sample-aws/.jdk8 | 0 .../function-sample-aws/build.gradle | 52 - .../gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../function-sample-aws/gradlew | 245 --- .../function-sample-aws/gradlew.bat | 92 - .../function-sample-aws/pom.xml | 139 -- .../java/example/FunctionConfiguration.java | 31 - .../src/main/resources/application.properties | 1 - .../src/main/resources/log4j.properties | 20 - .../src/test/java/example/MapTests.java | 31 - .../.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.jar | Bin 58727 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 109 - .../function-sample-azure-blob-trigger/mvnw | 316 --- .../mvnw.cmd | 188 -- .../pom.xml | 113 - .../AzureBlobTriggerDemoApplication.java | 36 - .../azureblobtriggerdemo/MyBlobFunction.java | 65 - .../src/main/resources/application.properties | 1 - .../src/main/resources/host.json | 7 - .../src/main/resources/local.settings.json | 8 - .../AzureBlobTriggerDemoApplicationTests.java | 13 - .../src/test/resource/sample.txt | 3 - .../.gitignore | 37 - .../README.adoc | 51 - .../build.gradle | 62 - .../gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../gradlew | 245 --- .../gradlew.bat | 92 - .../host.json | 7 - .../settings.gradle | 1 - .../azure/gradle/GradleDemoApplication.java | 60 - .../src/main/resources/application.properties | 1 - .../.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.jar | Bin 58727 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 94 - .../function-sample-azure-http-trigger/mvnw | 316 --- .../mvnw.cmd | 188 -- .../pom.xml | 111 - .../HttpTriggerDemoApplication.java | 47 - .../di/httptriggerdemo/MyAzureFunction.java | 72 - .../src/main/resources/application.properties | 1 - .../src/main/resources/host.json | 7 - .../HttptriggerDemoApplicationTests.java | 13 - .../.gitignore | 32 - .../README.md | 109 - .../function-sample-azure-kafka-trigger/mvnw | 316 --- .../mvnw.cmd | 188 -- .../pom.xml | 106 - .../src/main/azure/host.json | 16 - .../src/main/azure/local.settings.json | 13 - .../src/main/doc/kafka-publish-message.png | Bin 43717 -> 0 bytes .../src/main/doc/kafka-ui-topics.png | Bin 64359 -> 0 bytes .../src/main/doc/output-topic.png | Bin 104524 -> 0 bytes .../example/KafkaTriggerDemoApplication.java | 56 - .../main/java/example/UppercaseHandler.java | 75 - .../main/java/example/entity/KafkaEntity.java | 93 - .../java/example/entity/KafkaHeaders.java | 42 - .../main/resources/docker-compose-demo.yaml | 63 - .../wrapper/maven-wrapper.jar | Bin 58727 -> 0 bytes .../wrapper/maven-wrapper.properties | 2 - .../.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.jar | Bin 58727 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 122 -- .../function-sample-azure-time-trigger/mvnw | 316 --- .../mvnw.cmd | 188 -- .../pom.xml | 114 - .../TimeTriggerDemoApplication.java | 55 - .../di/timetriggerdemo/UppercaseHandler.java | 75 - .../src/main/resources/application.properties | 1 - .../src/main/resources/host.json | 7 - .../src/main/resources/local.settings.json | 8 - .../TimetriggerDemoApplicationTests.java | 13 - .../function-sample-azure-web/.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.jar | Bin 62547 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../function-sample-azure-web/README.adoc | 66 - .../function-sample-azure-web/mvnw | 308 --- .../function-sample-azure-web/mvnw.cmd | 205 -- .../function-sample-azure-web/pom.xml | 156 -- .../azure/web/AzureWebDemoApplication.java | 15 - .../java/com/example/azure/web/Country.java | 79 - .../example/azure/web/CountryController.java | 65 - .../example/azure/web/CountryRepository.java | 26 - .../src/main/resources/application.properties | 6 - .../src/main/resources/host.json | 7 - .../function-sample-azure/.gitignore | 4 - .../function-sample-azure/Dockerfile | 11 - .../function-sample-azure/README.adoc | 507 ----- .../function-sample-azure/pom.xml | 266 --- .../src/main/azure/host.json | 4 - .../src/main/azure/local.settings.json | 8 - .../src/main/java/example/Config.java | 84 - .../src/main/java/example/EchoHandler.java | 46 - .../ReactiveEchoCustomResultHandler.java | 63 - .../example/ReactiveUppercaseHandler.java | 42 - .../main/java/example/UppercaseHandler.java | 51 - .../.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 61 - .../function-sample-cloudevent-rsocket/mvnw | 310 --- .../mvnw.cmd | 182 -- .../pom.xml | 166 -- .../io/spring/cloudevent/DemoApplication.java | 28 - .../java/io/spring/cloudevent/Employee.java | 41 - .../java/io/spring/cloudevent/Person.java | 24 - .../src/main/resources/application.properties | 0 .../cloudevent/DemoApplicationTests.java | 83 - .../function-sample-cloudevent-sdk/.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 25 - .../function-sample-cloudevent-sdk/mvnw | 310 --- .../function-sample-cloudevent-sdk/mvnw.cmd | 182 -- .../function-sample-cloudevent-sdk/pom.xml | 159 -- .../io/spring/cloudevent/DemoApplication.java | 39 - .../src/main/resources/application.properties | 0 .../.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../README.adoc | 54 - .../function-sample-cloudevent-stream/mvnw | 310 --- .../mvnw.cmd | 182 -- .../function-sample-cloudevent-stream/pom.xml | 169 -- .../io/spring/cloudevent/DemoApplication.java | 47 - .../java/io/spring/cloudevent/Employee.java | 41 - .../java/io/spring/cloudevent/Person.java | 24 - .../src/main/resources/application.yaml | 15 - .../cloudevent/DemoApplicationTests.java | 83 - .../function-sample-cloudevent/.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../function-sample-cloudevent/README.adoc | 47 - .../images/rabbit-send-binary.png | Bin 185236 -> 0 bytes .../images/rabbit-send-structured.png | Bin 184685 -> 0 bytes .../function-sample-cloudevent/mvnw | 310 --- .../function-sample-cloudevent/mvnw.cmd | 182 -- .../function-sample-cloudevent/pom.xml | 153 -- .../io/spring/cloudevent/DemoApplication.java | 47 - .../java/io/spring/cloudevent/Employee.java | 41 - .../java/io/spring/cloudevent/Person.java | 24 - .../src/main/resources/application.properties | 1 - .../.jdk8 | 0 .../README.adoc | 7 - .../build.gradle | 93 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../gradlew | 164 -- .../gradlew.bat | 90 - .../pom.xml | 149 -- .../java/example/FunctionConfiguration.java | 56 - .../src/main/resources/application.properties | 2 - .../src/main/resources/log4j.properties | 20 - .../src/test/java/example/MapTests.java | 31 - .../README.adoc | 104 - .../function-sample-gcp-background/pom.xml | 122 -- .../com/example/BackgroundFunctionMain.java | 31 - .../main/java/com/example/PubSubMessage.java | 56 - .../src/main/resources/META-INF/MANIFEST.MF | 1 - .../function-sample-gcp-http/README.adoc | 46 - .../function-sample-gcp-http/pom.xml | 156 -- .../java/com/example/CloudFunctionMain.java | 36 - .../src/main/resources/META-INF/MANIFEST.MF | 1 - .../FunctionSampleGcpIntegrationTest.java | 38 - .../com/example/LocalServerTestSupport.java | 139 -- .../.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../function-sample-grpc-cloudevent/mvnw | 310 --- .../function-sample-grpc-cloudevent/mvnw.cmd | 182 -- .../function-sample-grpc-cloudevent/pom.xml | 148 -- .../grpc/demo/DemoGrpcApplication.java | 66 - .../src/main/proto/CloudEvent.proto | 49 - .../src/main/proto/CloudEventService.proto | 17 - .../src/main/resources/application.properties | 1 - .../grpc/demo/DemoGrpcApplicationTests.java | 13 - .../function-sample-kotlin-web/.gitignore | 33 - .../.mvn/wrapper/MavenWrapperDownloader.java | 117 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../function-sample-kotlin-web/README.adoc | 45 - .../images/rabbit-send-binary.png | Bin 185236 -> 0 bytes .../images/rabbit-send-structured.png | Bin 184685 -> 0 bytes .../function-sample-kotlin-web/mvnw | 310 --- .../function-sample-kotlin-web/mvnw.cmd | 182 -- .../function-sample-kotlin-web/pom.xml | 129 -- .../example/kotlin/DemoKotlinApplication.kt | 16 - .../example/kotlin/DemoKotlinConfiguration.kt | 18 - .../src/main/resources/application.properties | 0 .../function-sample-pof/build.gradle | 50 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-sample-pof/gradlew | 164 -- .../function-sample-pof/gradlew.bat | 90 - .../function-sample-pof/pom.xml | 131 -- .../src/main/java/functions/Application.java | 31 - .../src/main/java/functions/Greeter.java | 29 - .../function-sample-pojo/.jdk8 | 0 .../function-sample-pojo/build.gradle | 50 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-sample-pojo/gradlew | 164 -- .../function-sample-pojo/gradlew.bat | 90 - .../function-sample-pojo/pom.xml | 150 -- .../com/example/LowercaseConfiguration.java | 38 - .../java/com/example/SampleApplication.java | 110 - .../src/main/resources/application.properties | 4 - .../example/SampleApplicationMvcTests.java | 51 - .../com/example/SampleApplicationTests.java | 122 -- .../.gitignore | 26 - .../build.gradle | 43 - .../gradle/wrapper/gradle-wrapper.jar | Bin 54711 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../gradlew | 172 -- .../gradlew.bat | 84 - .../pom.xml | 140 -- .../settings.gradle | 1 - ...ionSampleSpringIntegrationApplication.java | 47 - .../src/main/resources/application.properties | 1 - ...mpleSpringIntegrationApplicationTests.java | 45 - .../README.md | 16 - .../compile.sh | 58 - .../function-sample-supplier-exporter/pom.xml | 155 -- .../com/example/demo/DemoApplication.java | 55 - .../META-INF/native-image/reflect-config.json | 7 - .../src/main/resources/application.properties | 4 - .../java/com/example/demo/ContainerTests.java | 65 - .../src/test/resources/bootstrap | 6 - .../function-sample/.jdk8 | 0 .../function-sample/build.gradle | 49 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-sample/gradlew | 164 -- .../function-sample/gradlew.bat | 90 - .../function-sample/pom.xml | 141 -- .../src/main/java/com/example/Client.java | 44 - .../java/com/example/SampleApplication.java | 67 - .../com/example/functions/CharCounter.java | 31 - .../java/com/example/functions/Exclaimer.java | 33 - .../java/com/example/functions/Greeter.java | 31 - .../resources/META-INF/thin-rabbit.properties | 5 - .../src/main/resources/application.properties | 2 - .../test/java/com/example/FunctionTests.java | 75 - .../example/SampleApplicationMvcTests.java | 68 - .../java/com/example/WebTestClientTests.java | 46 - spring-cloud-function-samples/pom.xml | 69 - spring-cloud-function-web/.jdk8 | 0 spring-cloud-function-web/pom.xml | 87 - spring-cloud-function-web/refactoring_notes | 6 - .../function/web/BasicStringConverter.java | 53 - .../function/web/FunctionHttpProperties.java | 83 - .../cloud/function/web/RestApplication.java | 36 - .../cloud/function/web/StringConverter.java | 27 - .../web/constants/WebRequestConstants.java | 55 - .../function/web/flux/FunctionController.java | 199 -- .../web/flux/FunctionHandlerMapping.java | 102 - .../web/flux/ReactorAutoConfiguration.java | 61 - .../function/FunctionEndpointInitializer.java | 279 --- .../function/web/mvc/FunctionController.java | 205 -- .../web/mvc/FunctionHandlerMapping.java | 126 -- .../web/mvc/ReactorAutoConfiguration.java | 57 - .../web/source/DestinationResolver.java | 29 - .../web/source/ExporterProperties.java | 187 -- .../FunctionExporterAutoConfiguration.java | 116 -- .../source/FunctionExporterInitializer.java | 106 - .../function/web/source/HttpSupplier.java | 110 - .../function/web/source/RequestBuilder.java | 33 - .../web/source/SimpleDestinationResolver.java | 32 - .../web/source/SimpleRequestBuilder.java | 83 - .../function/web/source/SupplierExporter.java | 214 -- .../FunctionWebRequestProcessingHelper.java | 249 --- .../function/web/util/FunctionWrapper.java | 84 - .../cloud/function/web/util/HeaderUtils.java | 103 - ...itional-spring-configuration-metadata.json | 11 - .../main/resources/META-INF/spring.factories | 6 - ...ot.autoconfigure.AutoConfiguration.imports | 3 - .../flux/FluxRestApplicationTests.java | 423 ---- .../function/mvc/MvcRestApplicationTests.java | 402 ---- .../cloud/function/scan/ComponentTests.java | 88 - .../test/ExplicitNonFunctionalTests.java | 62 - .../test/FunctionalExporterTests.java | 147 -- .../cloud/function/test/FunctionalTests.java | 58 - .../test/FunctionalWithInputListTests.java | 89 - .../test/FunctionalWithInputSetTests.java | 97 - .../function/test/HeadersToMessageTests.java | 68 - .../test/ImplicitNonFunctionalTests.java | 62 - .../MoreThenOneFunctionRootMappingTests.java | 69 - .../cloud/function/test/PojoTests.java | 94 - .../function/test/RestConfiguration.java | 67 - .../function/test/RestPojoConfiguration.java | 67 - .../cloud/function/web/TestSocketUtils.java | 75 - .../web/flux/HeadersToMessageTests.java | 130 -- .../web/flux/HttpGetIntegrationTests.java | 383 ---- .../web/flux/HttpPostIntegrationTests.java | 553 ----- .../cloud/function/web/flux/PrefixTests.java | 83 - .../function/web/flux/SingletonTests.java | 104 - .../FunctionEndpointInitializerMVCTests.java | 83 - .../FunctionEndpointInitializerTests.java | 231 --- .../web/function/UserSubmittedTests.java | 76 - .../function/web/mvc/DefaultRouteTests.java | 85 - .../web/mvc/GeneralIntegrationTests.java | 132 -- .../web/mvc/HeadersToMessageTests.java | 109 - .../web/mvc/HttpDeleteIntegrationTests.java | 155 -- .../web/mvc/HttpGetIntegrationTests.java | 402 ---- .../web/mvc/HttpPostIntegrationTests.java | 466 ----- .../function/web/mvc/MultipartFileTests.java | 100 - .../cloud/function/web/mvc/PrefixTests.java | 103 - .../web/mvc/RoutingFunctionTests.java | 259 --- .../function/web/mvc/SingletonTests.java | 100 - ...tionAutoConfigurationIntegrationTests.java | 129 -- ...figurationWithRetriesIntegrationTests.java | 137 -- ...urceAutoConfigurationIntegrationTests.java | 73 - .../web/source/WebAppIntegrationTests.java | 110 - .../src/test/resources/static/test.html | 3 - spring-cloud-starter-function-web/pom.xml | 30 - spring-cloud-starter-function-webflux/pom.xml | 29 - src/checkstyle/checkstyle-suppressions.xml | 6 - supplemental-ui/partials/nav-search.hbs | 11 + supplemental-ui/partials/search.hbs | 27 + 732 files changed, 177 insertions(+), 71914 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/deploy-docs.yml delete mode 100644 .mvn/maven.config delete mode 100644 .mvn/settings.xml delete mode 100644 .springformat delete mode 100644 .travis.yml delete mode 100644 CONTRIBUTING.adoc delete mode 100644 Guardfile delete mode 100644 LICENSE delete mode 100644 SECURITY.md rename docs/antora-playbook.yml => antora-playbook.yml (61%) delete mode 100644 docs/.github/workflows/deploy-docs.yml delete mode 100644 docs/antora.yml delete mode 100644 docs/modules/ROOT/assets/images/AWS-deploy.png delete mode 100644 docs/modules/ROOT/assets/images/remove.txt delete mode 100644 docs/modules/ROOT/assets/images/scf-azure-adapter.svg delete mode 100644 docs/modules/ROOT/nav.adoc delete mode 100644 docs/modules/ROOT/pages/README.adoc delete mode 100644 docs/modules/ROOT/pages/_intro.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/aws-intro.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/aws.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/azure-intro.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/azure.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/gcp-intro.adoc delete mode 100644 docs/modules/ROOT/pages/adapters/gcp.adoc delete mode 100644 docs/modules/ROOT/pages/functional.adoc delete mode 100644 docs/modules/ROOT/pages/getting-started.adoc delete mode 100644 docs/modules/ROOT/pages/index.adoc delete mode 100644 docs/modules/ROOT/pages/sagan-index.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc delete mode 100644 docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc delete mode 100644 docs/modules/ROOT/pages/spring-integration.adoc delete mode 100644 docs/pom.xml delete mode 100755 docs/src/main/asciidoc/ghpages.sh delete mode 100644 docs/src/main/asciidoc/images/AWS-deploy.png delete mode 100644 docs/src/main/asciidoc/images/remove.txt delete mode 100644 docs/src/main/asciidoc/images/scf-azure-adapter.svg delete mode 100644 docs/src/main/images/ce.png delete mode 100644 docs/src/main/images/message.png delete mode 100755 docs/src/main/ruby/generate_readme.sh delete mode 100644 pipeline.yml delete mode 100644 spring-cloud-function-adapters/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/README.adoc delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSCompanionAutoConfiguration.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSLambdaUtils.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSTypesMessageConverter.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoop.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/LambdaDestinationResolver.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/test/aws/AWSCustomRuntime.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoopTest.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/TestContext.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/README.adoc delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvoker.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/application.properties delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/spring-azure-function-banner.txt delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvokerTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/Pet.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetData.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetStoreSpringAppConfig.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetsController.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/TestExecutionContext.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/.jdk8 delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionInstanceInjector.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionUtil.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvoker.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/spring-azure-function-banner.txt delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/CustomFunctionInvokerTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/FunctionInvokerTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvokerTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/BuilderStub.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpRequestMessageStub.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpResponseMessageStub.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/TestExecutionContext.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/AzureFunctionInstanceInjectorTest.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/FunctionInstanceInjectorServiceLoadingTest.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/resources/log4j.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/FunctionInvoker.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/GcfJarLauncher.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayout.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayoutFactory.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/Context.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerBackgroundTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerHttpTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/PubSubMessage.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/FunctionInvokerIntegrationTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/LocalServerTestSupport.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.gitignore delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/README.md delete mode 100755 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw.cmd delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventGrpcAutoConfiguration.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventHandler.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventMessageConverter.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEvent.proto delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEventService.proto delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/application.properties delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/test/java/org/springframework/cloud/grpc/ce/SpringCloudFunctionGrpcCloudeventApplicationTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/.jdk8 delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/README.md delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/AbstractGrpcMessageConverter.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/FunctionGrpcProperties.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcAutoConfiguration.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcClientTemplate.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcMessageConverter.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServer.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServerMessageHandler.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcSpringMessageConverter.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcUtils.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/MessageHandlingHelper.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/proto/MessageService.proto delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/resources/application.properties delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/.jdk8 delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/README.md delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/.aws-sam/build.toml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/README.md delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/pom.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/assembly/bin.xml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetStoreSpringAppConfig.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetsController.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Error.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Pet.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/PetData.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/template.yml delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/FunctionClassUtils.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyAsyncContext.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyErrorController.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyFilterRegistration.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletRequest.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletResponse.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpSession.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyMvc.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletContext.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletRegistration.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ServerlessWebApplication.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/Pet.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetData.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java delete mode 100644 spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java delete mode 100644 spring-cloud-function-context/pom.xml delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/actuator/FunctionsEndpoint.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventHeaderEnricher.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageBuilder.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionExtensionConfiguration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionInvocationHelper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/DefaultMessageRoutingHandler.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionCatalog.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistry.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionTypeProcessor.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/MessageRoutingCallback.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PollableBean.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PostProcessingFunction.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionAroundWrapper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionCatalogEvent.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionRegistrationEvent.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionUnregistrationEvent.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/HeaderEnricher.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionsEndpointAutoConfiguration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/JsonMessageConverter.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/SmartCompositeMessageConverter.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalSpringBootTest.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalTestContextLoader.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/DefaultFunctionObservationConvention.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionContext.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservation.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservationConvention.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationAutoConfiguration.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationFunctionAroundWrapper.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionMessageUtils.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/PrimitiveTypesFromStringMessageConverter.java delete mode 100644 spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/SocketUtils.java delete mode 100644 spring-cloud-function-context/src/main/kotlin/org/springframework/cloud/function/context/config/CoroutinesUtils.kt delete mode 100644 spring-cloud-function-context/src/main/resources/META-INF/spring-configuration-metadata.json delete mode 100644 spring-cloud-function-context/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-context/src/main/resources/META-INF/spring/aot.factories delete mode 100644 spring-cloud-function-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventFunctionTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtilsAndBuilderTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HeaderMappingTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HybridFunctionalRegistrationTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/MessageRoutingCallbackTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryMultiInOutTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationConditionalLoadingTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/JsonMessageConverterTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/scan/TestFunction.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/string/FunctionalStringSourceTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/test/FunctionalTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/inject/FooConfiguration.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/scan/ScannedFunction.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/test/GenericFunction.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/userissues/UserIssuesTests.java delete mode 100644 spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java delete mode 100644 spring-cloud-function-context/src/test/resources/avro/sensor.avsc delete mode 100644 spring-cloud-function-context/src/test/resources/greeter.jar delete mode 100644 spring-cloud-function-core/.jdk8 delete mode 100644 spring-cloud-function-core/pom.xml delete mode 100644 spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionInvocationHelper.java delete mode 100644 spring-cloud-function-dependencies/pom.xml delete mode 100644 spring-cloud-function-deployer/.gitignore delete mode 100644 spring-cloud-function-deployer/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-deployer/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-deployer/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/demo-stream-0.0.1-SNAPSHOT.jar delete mode 100644 spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/demo-stream-0.0.1-SNAPSHOT.pom delete mode 100644 spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/maven-metadata-local.xml delete mode 100644 spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/maven-metadata-local.xml delete mode 100755 spring-cloud-function-deployer/mvnw delete mode 100644 spring-cloud-function-deployer/mvnw.cmd delete mode 100644 spring-cloud-function-deployer/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/MyFn.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/RepeaterApplication.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/SimpleFunctionAppApplication.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/SimpleFunctionAppApplication.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java delete mode 100644 spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootjar-multi/src/main/java/function/example/Repeater.java delete mode 100644 spring-cloud-function-deployer/src/it/bootjar/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/ReverseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java delete mode 100644 spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/bootjarnostart/src/main/java/function/example/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/settings.xml delete mode 100644 spring-cloud-function-deployer/src/it/simplestjar/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/simplestjar/src/main/java/function/example/EchoCloudEventFunction.java delete mode 100644 spring-cloud-function-deployer/src/it/simplestjarcs/pom.xml delete mode 100644 spring-cloud-function-deployer/src/it/simplestjarcs/src/main/java/functions/UpperCaseFunction.java delete mode 100644 spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployerContextUtils.java delete mode 100644 spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionArchiveDeployer.java delete mode 100644 spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerConfiguration.java delete mode 100644 spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerProperties.java delete mode 100644 spring-cloud-function-deployer/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-deployer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java delete mode 100644 spring-cloud-function-integration/pom.xml delete mode 100644 spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowAutoConfiguration.java delete mode 100644 spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowBuilder.java delete mode 100644 spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowDefinition.java delete mode 100644 spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java delete mode 100644 spring-cloud-function-integration/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java delete mode 100644 spring-cloud-function-kotlin/.jdk8 delete mode 100644 spring-cloud-function-kotlin/README.adoc delete mode 100644 spring-cloud-function-kotlin/pom.xml delete mode 100644 spring-cloud-function-kotlin/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinSuspendTests.java delete mode 100644 spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/ComponentUppercase.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinComponentFunction.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendFlowLambdasConfiguration.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendLambdasConfiguration.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/AwsKotlinTestsTests.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/KotlinAwsLambdasConfiguration.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageSuspendTests.kt delete mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageTests.kt delete mode 100644 spring-cloud-function-rsocket/.jdk8 delete mode 100644 spring-cloud-function-rsocket/NOTES.txt delete mode 100644 spring-cloud-function-rsocket/README.md delete mode 100644 spring-cloud-function-rsocket/pom.xml delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketMessageHandler.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketUtils.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonDecoder.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonEncoder.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketAutoConfiguration.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketCustomizerConfiguration.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketForwardingFunction.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketFunctionProperties.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketListenerFunction.java delete mode 100644 spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketRoutingAutoConfiguration.java delete mode 100644 spring-cloud-function-rsocket/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-rsocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessageRoutingCallbackRSocketTests.java delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessagingTests.java delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationRoutingTests.java delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RoutingBrokerTests.java delete mode 100644 spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/TestSocketUtils.java delete mode 100644 spring-cloud-function-rsocket/src/test/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/.jdk8 delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/build.gradle delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-functional-sample-aws/gradlew delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/pom.xml delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/TestFunction.java delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/log4j.properties delete mode 100644 spring-cloud-function-samples/function-functional-sample-aws/src/test/java/example/MapTests.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom-bean/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom-bean/src/assembly/zip.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/java/com/example/LambdaApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/application.properties delete mode 100755 spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/bootstrap delete mode 100755 spring-cloud-function-samples/function-sample-aws-custom-bean/src/test/resources/testBootstrap delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/src/assembly/zip.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/application.properties delete mode 100755 spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/bootstrap delete mode 100644 spring-cloud-function-samples/function-sample-aws-custom/src/test/java/com/example/LambdaApplicationTests.java delete mode 100755 spring-cloud-function-samples/function-sample-aws-custom/src/test/resources/testBootstrap delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/Dockerfile delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/README.md delete mode 100755 spring-cloud-function-samples/function-sample-aws-native/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/assembly/java.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/assembly/native.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/main/java/com/example/demo/NativeUppercaseApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/shell/java/bootstrap delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/shell/native/bootstrap delete mode 100644 spring-cloud-function-samples/function-sample-aws-native/src/test/java/com/example/demo/NativeUppercaseApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-aws-routing/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/src/main/java/example/FunctionConfiguration.java delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/log4j.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws-routing/src/test/java/example/MapTests.java delete mode 100644 spring-cloud-function-samples/function-sample-aws/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample-aws/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-aws/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-aws/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-aws/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java delete mode 100644 spring-cloud-function-samples/function-sample-aws/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws/src/main/resources/log4j.properties delete mode 100644 spring-cloud-function-samples/function-sample-aws/src/test/java/example/MapTests.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/MyBlobFunction.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/local.settings.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/resource/sample.txt delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/settings.gradle delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/java/org/scf/azure/gradle/GradleDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/HttpTriggerDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/MyAzureFunction.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-http-trigger/src/test/java/com/example/azure/di/httptriggerdemo/HttptriggerDemoApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/README.md delete mode 100755 spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/local.settings.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-publish-message.png delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-ui-topics.png delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/output-topic.png delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/KafkaTriggerDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/UppercaseHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaEntity.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaHeaders.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/resources/docker-compose-demo.yaml delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/TimeTriggerDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/UppercaseHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/local.settings.json delete mode 100644 spring-cloud-function-samples/function-sample-azure-time-trigger/src/test/java/com/example/azure/di/timetriggerdemo/TimetriggerDemoApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-azure-web/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/AzureWebDemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/Country.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryController.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryRepository.java delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-azure-web/src/main/resources/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-azure/Dockerfile delete mode 100644 spring-cloud-function-samples/function-sample-azure/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-azure/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/azure/host.json delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/java/example/Config.java delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/java/example/EchoHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveEchoCustomResultHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveUppercaseHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/java/example/UppercaseHandler.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/DemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Employee.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Person.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/test/java/io/spring/cloudevent/DemoApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/java/io/spring/cloudevent/DemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/README.adoc delete mode 100755 spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/DemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Employee.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Person.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/resources/application.yaml delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent-stream/src/test/java/io/spring/cloudevent/DemoApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-binary.png delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-structured.png delete mode 100755 spring-cloud-function-samples/function-sample-cloudevent/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Employee.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Person.java delete mode 100644 spring-cloud-function-samples/function-sample-cloudevent/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-functional-aws-routing/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/java/example/FunctionConfiguration.java delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/log4j.properties delete mode 100644 spring-cloud-function-samples/function-sample-functional-aws-routing/src/test/java/example/MapTests.java delete mode 100644 spring-cloud-function-samples/function-sample-gcp-background/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-gcp-background/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/BackgroundFunctionMain.java delete mode 100644 spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/PubSubMessage.java delete mode 100644 spring-cloud-function-samples/function-sample-gcp-background/src/main/resources/META-INF/MANIFEST.MF delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/src/main/java/com/example/CloudFunctionMain.java delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/src/main/resources/META-INF/MANIFEST.MF delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/FunctionSampleGcpIntegrationTest.java delete mode 100644 spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/LocalServerTestSupport.java delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/java/com/example/grpc/demo/DemoGrpcApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEvent.proto delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEventService.proto delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-grpc-cloudevent/src/test/java/com/example/grpc/demo/DemoGrpcApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/README.adoc delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-binary.png delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-structured.png delete mode 100755 spring-cloud-function-samples/function-sample-kotlin-web/mvnw delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/mvnw.cmd delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinApplication.kt delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinConfiguration.kt delete mode 100644 spring-cloud-function-samples/function-sample-kotlin-web/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-pof/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-pof/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-pof/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-pof/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-pof/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-pof/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Application.java delete mode 100644 spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Greeter.java delete mode 100644 spring-cloud-function-samples/function-sample-pojo/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample-pojo/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-pojo/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-pojo/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-pojo/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-pojo/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-pojo/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/LowercaseConfiguration.java delete mode 100644 spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/SampleApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-pojo/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationMvcTests.java delete mode 100644 spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/.gitignore delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/gradle/wrapper/gradle-wrapper.properties delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/settings.gradle delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/src/main/java/example/FunctionSampleSpringIntegrationApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-spring-integration/src/test/java/example/FunctionSampleSpringIntegrationApplicationTests.java delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/README.md delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/ContainerTests.java delete mode 100755 spring-cloud-function-samples/function-sample-supplier-exporter/src/test/resources/bootstrap delete mode 100644 spring-cloud-function-samples/function-sample/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample/gradlew delete mode 100644 spring-cloud-function-samples/function-sample/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample/pom.xml delete mode 100644 spring-cloud-function-samples/function-sample/src/main/java/com/example/Client.java delete mode 100644 spring-cloud-function-samples/function-sample/src/main/java/com/example/SampleApplication.java delete mode 100644 spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/CharCounter.java delete mode 100644 spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Exclaimer.java delete mode 100644 spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Greeter.java delete mode 100644 spring-cloud-function-samples/function-sample/src/main/resources/META-INF/thin-rabbit.properties delete mode 100644 spring-cloud-function-samples/function-sample/src/main/resources/application.properties delete mode 100644 spring-cloud-function-samples/function-sample/src/test/java/com/example/FunctionTests.java delete mode 100644 spring-cloud-function-samples/function-sample/src/test/java/com/example/SampleApplicationMvcTests.java delete mode 100644 spring-cloud-function-samples/function-sample/src/test/java/com/example/WebTestClientTests.java delete mode 100644 spring-cloud-function-samples/pom.xml delete mode 100644 spring-cloud-function-web/.jdk8 delete mode 100644 spring-cloud-function-web/pom.xml delete mode 100644 spring-cloud-function-web/refactoring_notes delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/BasicStringConverter.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionHttpProperties.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestApplication.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/StringConverter.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/constants/WebRequestConstants.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionHandlerMapping.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionController.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/ReactorAutoConfiguration.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/DestinationResolver.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/ExporterProperties.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterInitializer.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/HttpSupplier.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/RequestBuilder.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleDestinationResolver.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleRequestBuilder.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWrapper.java delete mode 100644 spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/HeaderUtils.java delete mode 100644 spring-cloud-function-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json delete mode 100644 spring-cloud-function-web/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/flux/FluxRestApplicationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/mvc/MvcRestApplicationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/scan/ComponentTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ExplicitNonFunctionalTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputListTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputSetTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/HeadersToMessageTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ImplicitNonFunctionalTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/MoreThenOneFunctionRootMappingTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/PojoTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestConfiguration.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestPojoConfiguration.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/TestSocketUtils.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HeadersToMessageTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpGetIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpPostIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/PrefixTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/SingletonTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerMVCTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/UserSubmittedTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/DefaultRouteTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/GeneralIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HeadersToMessageTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpDeleteIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpGetIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpPostIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/MultipartFileTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/PrefixTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/RoutingFunctionTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/SingletonTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationWithRetriesIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/SourceAutoConfigurationIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/WebAppIntegrationTests.java delete mode 100644 spring-cloud-function-web/src/test/resources/static/test.html delete mode 100644 spring-cloud-starter-function-web/pom.xml delete mode 100644 spring-cloud-starter-function-webflux/pom.xml delete mode 100644 src/checkstyle/checkstyle-suppressions.xml create mode 100644 supplemental-ui/partials/nav-search.hbs create mode 100644 supplemental-ui/partials/search.hbs diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e65ee4533..000000000 --- a/.editorconfig +++ /dev/null @@ -1,14 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -[*] -indent_style = tab -indent_size = 4 -end_of_line = lf -insert_final_newline = true - -[*.yml] -indent_style = space -indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index d3204a48c..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: waiting-for-triage -assignees: '' - ---- - -**Describe the bug** -Please provide details of the problem, including the version of Spring Cloud that you -are using. - -**Sample** -If possible, please provide a test case or sample application that reproduces -the problem. This makes it much easier for us to diagnose the problem and to verify that -we have fixed it. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index b2e33c5fa..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: waiting-for-triage -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 000000000..31c46dcb0 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,53 @@ +name: Deploy Docs +run-name: ${{ format('{0} ({1})', github.workflow, github.event.inputs.build-refname || 'all') }} +on: + workflow_dispatch: + inputs: + build-refname: + description: Enter git refname to build (e.g., 5.7.x). + required: false + push: + branches: docs-build +env: + GRADLE_ENTERPRISE_SECRET_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} +permissions: + contents: write +jobs: + build: + if: github.repository_owner == 'spring-cloud' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 5 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up refname build + if: github.event.inputs.build-refname + run: | + git fetch --depth 1 https://github.com/$GITHUB_REPOSITORY ${{ github.event.inputs.build-refname }} + export BUILD_REFNAME=${{ github.event.inputs.build-refname }} + echo "BUILD_REFNAME=$BUILD_REFNAME" >> $GITHUB_ENV + export BUILD_VERSION=$(git cat-file --textconv FETCH_HEAD:pom.xml | python3 -c "import xml.etree.ElementTree as xml; from sys import stdin; print(xml.parse(stdin).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)") + echo BUILD_VERSION=$BUILD_VERSION >> $GITHUB_ENV + - name: Run Antora + run: | + ./mvnw --no-transfer-progress -B antora + - name: Publish Docs + uses: rwinch/spring-doc-actions/rsync-antora-reference@httpdocs-path + with: + docs-username: ${{ secrets.DOCS_USERNAME }} + docs-host: ${{ secrets.DOCS_HOST }} + docs-ssh-key: ${{ secrets.DOCS_SSH_KEY }} + docs-ssh-host-key: ${{ secrets.DOCS_SSH_HOST_KEY }} + site-path: target/antora/site + - name: Bust Cloudflare Cache + uses: spring-io/spring-doc-actions/bust-cloudflare-antora-cache@v0.0.11 + with: + context-root: spring-cloud-function + cloudflare-zone-id: ${{ secrets.CLOUDFLARE_ZONE_ID }} + cloudflare-cache-token: ${{ secrets.CLOUDFLARE_CACHE_TOKEN }} diff --git a/.gitignore b/.gitignore index 51bb91bbc..6be8a4a16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,22 @@ -/application.yml -/application.properties -asciidoctor.css -*~ -.#* -*# target/ -build/ -bin/ -.sts4-cache/ -.attach_pid* -.m2/ -.gradle/ -_site/ -.vscode/ -.classpath -.project .settings/ +.project +.classpath +*.orig .springBeans +.factorypath +.sts4-cache +.ant-targets-build.xml +src/ant/.ant-targets-upload-dist.xml +*.sonar4clipse* .DS_Store -*.sw* *.iml *.ipr *.iws -.idea/ -.factorypath -.checkstyle -coverage-error.log -.apt_generated -credentials.yml -.flattened-pom.xml -pom.xml.versionsBackup +/.idea/ +*.graphml +node +node_modules +build +package.json +package-lock.json diff --git a/.mvn/jvm.config b/.mvn/jvm.config index 52b2013a8..0e7dabeff 100644 --- a/.mvn/jvm.config +++ b/.mvn/jvm.config @@ -1 +1 @@ --Xmx1024m -XX:CICompilerCount=1 -noverify -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom \ No newline at end of file +-Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom \ No newline at end of file diff --git a/.mvn/maven.config b/.mvn/maven.config deleted file mode 100644 index 3b8cf46e1..000000000 --- a/.mvn/maven.config +++ /dev/null @@ -1 +0,0 @@ --DaltSnapshotDeploymentRepository=repo.spring.io::default::https://repo.spring.io/libs-snapshot-local -P spring diff --git a/.mvn/settings.xml b/.mvn/settings.xml deleted file mode 100644 index 2e2841999..000000000 --- a/.mvn/settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - sonatype-nexus-staging - ${env.sonatype_username} - ${env.sonatype_password} - - - repo.spring.io - ${env.spring_username} - ${env.spring_password} - - - diff --git a/.springformat b/.springformat deleted file mode 100644 index e69de29bb..000000000 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9e59b8e23..000000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: java -jdk: - - oraclejdk8 -sudo: required -cache: - directories: - - $HOME/.m2 -install: true -before_script: ./mvnw install -q -U -DskipTests=true -Dmaven.test.redirectTestOutputToFile=true -script: ./mvnw install -q -nsu -Dmaven.test.redirectTestOutputToFile=true -dist: trusty diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc deleted file mode 100644 index 8e009c69d..000000000 --- a/CONTRIBUTING.adoc +++ /dev/null @@ -1,3 +0,0 @@ -If you have not previously done so, please fill out and -submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement]. - diff --git a/Guardfile b/Guardfile deleted file mode 100644 index da91d82bb..000000000 --- a/Guardfile +++ /dev/null @@ -1,12 +0,0 @@ -require 'asciidoctor' -require 'erb' -require './src/main/ruby/readme.rb' - -options = {:mkdirs => true, :safe => :unsafe, :attributes => ['linkcss', 'allow-uri-read']} - -guard 'shell' do - watch(/^src\/[A-Z-a-z][^#]*\.adoc$/) {|m| - SpringCloud::Build.render_file('src/main/asciidoc/README.adoc', :to_file => './README.adoc') - Asciidoctor.render_file('src/main/asciidoc/spring-cloud-cli.adoc', options.merge(:to_dir => 'target/generated-docs')) - } -end diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 62589edd1..000000000 --- a/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/README.adoc b/README.adoc index 139cdf601..e15e4f9f2 100644 --- a/README.adoc +++ b/README.adoc @@ -1,411 +1,23 @@ -//// -DO NOT EDIT THIS FILE. IT WAS GENERATED. -Manual changes to this file will be lost when it is generated again. -Edit the files in the src/main/asciidoc/ directory instead. -//// += Spring Cloud Function Docs Build +You're currently viewing the Antora playbook branch. +The playbook branch hosts the docs build that is used to build and publish the production docs site. -:branch: master +The Spring Cloud Function reference docs are built using https://antora.org[Antora]. +This README covers how to build the docs in a software branch as well as how to build the production docs site locally. -image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={branch}[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] +== Building the Site -== Introduction - -Spring Cloud Function is a project with the following high-level goals: - -* Promote the implementation of business logic via functions. -* Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task. -* Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS). -* Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers. - -It abstracts away all of the transport details and -infrastructure, allowing the developer to keep all the familiar tools -and processes, and focus firmly on business logic. - -Here's a complete, executable, testable Spring Boot application -(implementing a simple string manipulation): - -[source,java] ----- -@SpringBootApplication -public class Application { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} ----- - -It's just a Spring Boot application, so it can be built, run and -tested, locally and in a CI build, the same way as any other Spring -Boot application. The `Function` is from `java.util` and `Flux` is a -https://www.reactive-streams.org/[Reactive Streams] `Publisher` from -https://projectreactor.io/[Project Reactor]. The function can be -accessed over HTTP or messaging. - -Spring Cloud Function has the following features: - -* _Choice of programming styles - reactive, imperative or hybrid._ -* _Function composition and adaptation (e.g., composing imperative functions with reactive)._ -* _Support for reactive function with multiple inputs and outputs allowing merging, joining and other complex streaming operation to be handled by functions._ -* _Transparent type conversion of inputs and outputs._ -* _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ -* _Adapters to expose function to the outside world as HTTP endpoints etc._ -* _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], and possibly other "serverless" service providers._ - -== Getting Started - -Build from the command line (and "install" the samples): - ----- -$ ./mvnw clean install ----- - -(If you like to YOLO add `-DskipTests`.) - -Run one of the samples, e.g. - ----- -$ java -jar spring-cloud-function-samples/function-sample/target/*.jar ----- - -This runs the app and exposes its functions over HTTP, so you can -convert a string to uppercase, like this: - ----- -$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello -HELLO ----- - -You can convert multiple strings (a `Flux`) by separating them -with new lines +You can build the entire site by invoking the following on the docs-build branch and then viewing the site at `target/site/index.html` +[source,bash] ---- -$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello -> World' -HELLOWORLD +./mvnw antora ---- -(You can use `^Q^J` in a terminal to insert a new line in a literal -string like that.) - -== Building - -:jdkversion: 17 - -=== Basic Compile and Test - -To build the source you will need to install JDK {jdkversion}. - -Spring Cloud uses Maven for most build-related activities, and you -should be able to get off the ground quite quickly by cloning the -project you are interested in and typing +== Building a Specific Branch +[source,bash] ---- -$ ./mvnw install +./mvnw antora ---- - -NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command -in place of `./mvnw` in the examples below. If you do that you also -might need to add `-P spring` if your local Maven settings do not -contain repository declarations for spring pre-release artifacts. - -NOTE: Be aware that you might need to increase the amount of memory -available to Maven by setting a `MAVEN_OPTS` environment variable with -a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in -the `.mvn` configuration, so if you find you have to do it to make a -build succeed, please raise a ticket to get the settings added to -source control. - -The projects that require middleware (i.e. Redis) for testing generally -require that a local instance of [Docker](https://www.docker.com/get-started) is installed and running. - - -=== Documentation - -The spring-cloud-build module has a "docs" profile, and if you switch -that on it will try to build asciidoc sources from -`src/main/asciidoc`. As part of that process it will look for a -`README.adoc` and process it by loading all the includes, but not -parsing or rendering it, just copying it to `${main.basedir}` -(defaults to `${basedir}`, i.e. the root of the project). If there are -any changes in the README it will then show up after a Maven build as -a modified file in the correct place. Just commit it and push the change. - -=== Working with the code -If you don't have an IDE preference we would recommend that you use -https://www.springsource.com/developer/sts[Spring Tools Suite] or -https://eclipse.org[Eclipse] when working with the code. We use the -https://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools -should also work without issue as long as they use Maven 3.3.3 or better. - -==== Activate the Spring Maven profile -Spring Cloud projects require the 'spring' Maven profile to be activated to resolve -the spring milestone and snapshot repositories. Use your preferred IDE to set this -profile to be active, or you may experience build errors. - -==== Importing into eclipse with m2eclipse -We recommend the https://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with -eclipse. If you don't already have m2eclipse installed it is available from the "eclipse -marketplace". - -NOTE: Older versions of m2e do not support Maven 3.3, so once the -projects are imported into Eclipse you will also need to tell -m2eclipse to use the right profile for the projects. If you -see many different errors related to the POMs in the projects, check -that you have an up to date installation. If you can't upgrade m2e, -add the "spring" profile to your `settings.xml`. Alternatively you can -copy the repository settings from the "spring" profile of the parent -pom into your `settings.xml`. - -==== Importing into eclipse without m2eclipse -If you prefer not to use m2eclipse you can generate eclipse project metadata using the -following command: - -[indent=0] ----- - $ ./mvnw eclipse:eclipse ----- - -The generated eclipse projects can be imported by selecting `import existing projects` -from the `file` menu. - - -== Contributing - -:spring-cloud-build-branch: master - -Spring Cloud is released under the non-restrictive Apache 2.0 license, -and follows a very standard Github development process, using Github -tracker for issues and merging pull requests into master. If you want -to contribute even something trivial please do not hesitate, but -follow the guidelines below. - -=== Sign the Contributor License Agreement -Before we accept a non-trivial patch or pull request we will need you to sign the -https://cla.pivotal.io/sign/spring[Contributor License Agreement]. -Signing the contributor's agreement does not grant anyone commit rights to the main -repository, but it does mean that we can accept your contributions, and you will get an -author credit if we do. Active contributors might be asked to join the core team, and -given the ability to merge pull requests. - -=== Code of Conduct -This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of -conduct]. By participating, you are expected to uphold this code. Please report -unacceptable behavior to spring-code-of-conduct@pivotal.io. - -=== Code Conventions and Housekeeping -None of these is essential for a pull request, but they will all help. They can also be -added after the original pull request but before a merge. - -* Use the Spring Framework code format conventions. If you use Eclipse - you can import formatter settings using the - `eclipse-code-formatter.xml` file from the - https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring - Cloud Build] project. If using IntelliJ, you can use the - https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter - Plugin] to import the same file. -* Make sure all new `.java` files to have a simple Javadoc class comment with at least an - `@author` tag identifying you, and preferably at least a paragraph on what the class is - for. -* Add the ASF license header comment to all new `.java` files (copy from existing files - in the project) -* Add yourself as an `@author` to the .java files that you modify substantially (more - than cosmetic changes). -* Add some Javadocs and, if you change the namespace, some XSD doc elements. -* A few unit tests would help a lot as well -- someone has to do it. -* If no-one else is using your branch, please rebase it against the current master (or - other target branch in the main project). -* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], - if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit - message (where XXXX is the issue number). - -=== Checkstyle - -Spring Cloud Build comes with a set of checkstyle rules. You can find them in the `spring-cloud-build-tools` module. The most notable files under the module are: - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    └── checkstyle.xml <1> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules - -==== Checkstyle configuration - -Checkstyle rules are *disabled by default*. To add checkstyle to your project just define the following properties and plugins. - -.pom.xml ----- - -true <1> - true - <2> - true - <3> - - - - - <4> - io.spring.javaformat - spring-javaformat-maven-plugin - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - ----- -<1> Fails the build upon Checkstyle errors -<2> Fails the build upon Checkstyle violations -<3> Checkstyle analyzes also the test sources -<4> Add the Spring Java Format plugin that will reformat your code to pass most of the Checkstyle formatting rules -<5> Add checkstyle plugin to your build and reporting phases - -If you need to suppress some rules (e.g. line length needs to be longer), then it's enough for you to define a file under `${project.root}/src/checkstyle/checkstyle-suppressions.xml` with your suppressions. Example: - -.projectRoot/src/checkstyle/checkstyle-suppresions.xml ----- - - - - - - ----- - -It's advisable to copy the `${spring-cloud-build.rootFolder}/.editorconfig` and `${spring-cloud-build.rootFolder}/.springformat` to your project. That way, some default formatting rules will be applied. You can do so by running this script: - -```bash -$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig -$ touch .springformat -``` - -=== IDE setup - -==== Intellij IDEA - -In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin. -The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project. - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    ├── checkstyle.xml <1> -    └── intellij -       ├── Intellij_Project_Defaults.xml <4> -       └── Intellij_Spring_Boot_Java_Conventions.xml <5> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules -<4> Project defaults for Intellij that apply most of Checkstyle rules -<5> Project style conventions for Intellij that apply most of Checkstyle rules - -.Code style - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-code-style.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Code style`. There click on the icon next to the `Scheme` section. There, click on the `Import Scheme` value and pick the `Intellij IDEA code style XML` option. Import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml` file. - -.Inspection profiles - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-inspections.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Inspections`. There click on the icon next to the `Profile` section. There, click on the `Import Profile` and import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml` file. - -.Checkstyle - -To have Intellij work with Checkstyle, you have to install the `Checkstyle` plugin. It's advisable to also install the `Assertions2Assertj` to automatically convert the JUnit assertions - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-checkstyle.png[Checkstyle] - -Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables: - -- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL. -- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL. -- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`. - -IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources. - -=== Duplicate Finder - -Spring Cloud Build brings along the `basepom:duplicate-finder-maven-plugin`, that enables flagging duplicate and conflicting classes and resources on the java classpath. - -==== Duplicate Finder configuration - -Duplicate finder is *enabled by default* and will run in the `verify` phase of your Maven build, but it will only take effect in your project if you add the `duplicate-finder-maven-plugin` to the `build` section of the projecst's `pom.xml`. - -.pom.xml -[source,xml] ----- - - - - org.basepom.maven - duplicate-finder-maven-plugin - - - ----- - -For other properties, we have set defaults as listed in the https://github.com/basepom/duplicate-finder-maven-plugin/wiki[plugin documentation]. - -You can easily override them but setting the value of the selected property prefixed with `duplicate-finder-maven-plugin`. For example, set `duplicate-finder-maven-plugin.skip` to `true` in order to skip duplicates check in your build. - -If you need to add `ignoredClassPatterns` or `ignoredResourcePatterns` to your setup, make sure to add them in the plugin configuration section of your project: - -[source,xml] ----- - - - - org.basepom.maven - duplicate-finder-maven-plugin - - - org.joda.time.base.BaseDateTime - .*module-info - - - changelog.txt - - - - - - - ----- - diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 36ef17ca6..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,8 +0,0 @@ -**Describe the bug** -Please provide details of the problem, including the version of Spring Cloud that you -are using. - -**Sample** -If possible, please provide a test case or sample application that reproduces -the problem. This makes it much easier for us to diagnose the problem and to verify that -we have fixed it. diff --git a/docs/antora-playbook.yml b/antora-playbook.yml similarity index 61% rename from docs/antora-playbook.yml rename to antora-playbook.yml index 9a70e676c..29692089d 100644 --- a/docs/antora-playbook.yml +++ b/antora-playbook.yml @@ -6,38 +6,39 @@ antora: - '@antora/collector-extension' - '@antora/atlas-extension' - require: '@springio/antora-extensions/root-component-extension' - root_component_name: 'PROJECT_WITHOUT_SPRING' - # FIXME: Run antora once using this extension to migrate to the Asciidoc Tabs syntax - # and then remove this extension - - require: '@springio/antora-extensions/tabs-migration-extension' - unwrap_example_block: always - save_result: true + root_component_name: 'cloud-function' site: - title: PROJECT_FULL_NAME - url: https://docs.spring.io/PROJECT_NAME/reference/ + title: Spring Cloud Function + url: https://docs.spring.io/spring-cloud-function/reference + robots: allow +git: + ensure_git_suffix: false content: sources: - - url: ./.. - branches: HEAD + - url: https://github.com/spring-cloud/spring-cloud-function + # Refname matching: + # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ + branches: [ main ] + tags: [ '({4..9}).+({1..9}).+({0..9})?(-{RC,M}+({0..9}))', '!4.1.0-M1' ] start_path: docs - worktrees: true asciidoc: attributes: page-stackoverflow-url: https://stackoverflow.com/tags/spring-cloud page-pagination: '' hide-uri-scheme: '@' tabs-sync-option: '@' - chomp: 'all' extensions: - '@asciidoctor/tabs' - '@springio/asciidoctor-extensions' - sourcemap: true urls: + latest_version_segment_strategy: redirect:to latest_version_segment: '' + redirect_facility: httpd +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip + snapshot: true runtime: log: failure_level: warn format: pretty -ui: - bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip diff --git a/docs/.github/workflows/deploy-docs.yml b/docs/.github/workflows/deploy-docs.yml deleted file mode 100644 index be4b92dfc..000000000 --- a/docs/.github/workflows/deploy-docs.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Deploy Docs -on: - push: - branches-ignore: [ gh-pages ] - tags: '**' - repository_dispatch: - types: request-build-reference # legacy - #schedule: - #- cron: '0 10 * * *' # Once per day at 10am UTC - workflow_dispatch: -permissions: - actions: write -jobs: - build: - runs-on: ubuntu-latest - # if: github.repository_owner == 'spring-cloud' - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: docs-build - fetch-depth: 1 - - name: Dispatch (partial build) - if: github.ref_type == 'branch' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }} - - name: Dispatch (full build) - if: github.ref_type == 'tag' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) diff --git a/docs/antora.yml b/docs/antora.yml deleted file mode 100644 index 15b346da0..000000000 --- a/docs/antora.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: PROJECT_WITHOUT_SPRING -version: true -title: PROJECT_NAME -nav: - - modules/ROOT/nav.adoc -ext: - collector: - run: - command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests - local: true - scan: - dir: ./target/classes/antora-resources/ diff --git a/docs/modules/ROOT/assets/images/AWS-deploy.png b/docs/modules/ROOT/assets/images/AWS-deploy.png deleted file mode 100644 index c840e1396736e81c706e1bcac783b2bee781b6db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 602969 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­MgUgQui)8rD4Z+Kfab65N>#l9mCteq3SFI_D*| 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

5voOCh=mB8RUQqe$O5`Xagy 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

xc*jnzqrSq&oreJHD}7 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μ)>GVqz$~d4<1cx5{+|Y;F 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

h?H6~nCIjMT#tHa0QI8Hk(0VxeUH_c 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

96$Z%RXS-skP;6 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

qf9;R_CtL3AY| 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�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�Tp0By^B5RIy)6}9z zO-FbGxI=h$mz8q)_fvL5^OZg&AEzGhryq8}vaPcjY~+5)ehWuyyl6{V)~~*5Y5$lt zBGoHH(|u@j*JS3jy>xcJFGl&he0St&Vv(NhNz&+Q{6EB<|Ba@?-oPOyn3``Dq<3ZqCfuybcqG%^!y>&JkOq?Q9|I6={)vKaSfoBmXU{nM%|HM>b+1;oSx+^pW?WV$6Z<#0-VetvvE}^C6py=2 z;}cexbh@8i77smfg#2ndui2rAX%S&_J(*dHYfi=PmwuM$bd@-xzZ|4f9M?RE?G)4& zXK=Aw#j;73B^1A3iPEkXMSgI~{&0@z>>}YKv$sEOq6u-sicR^1lxF#LI4n+$_u3hB zO;;Zk?fyt9<<}x%;ZwXH<{fdQFVpZ`d8hWWGJ{g-=qsVPQ{kI|I8)@E;qE`dw3!MI z8(ne#*qhDl++>fWgp1X*(KYXrZM)+GflHS|!zw+WZ{q*giksgyZ6T&kOD{>I&cq2W z<)dk}BvJ)Q15^qowF1Ypbzu)9oj64}$CcE4p?{RwcG4%&3?w~f)8EhSk`C0iV~eW_ z3$4LNgG+c&kZ6MzkV%O7A}1TzodKEn7Xul>zzVAA|F|GpZoIVQU0ouq)H!My20S98ikOOO20fX{;{;{ zO4l&O3!EFUYeQHTXQM)>$70JhxltkY1NcyoANbyn=`Xzuzjcc>e3X0T^#P&bw;3bt z1}}&My%aeV|NQ2p0HC1`HeJoe>F?x%&j+?P;shY#roHv|-u##3l17e|`y?c!OvFyH ziX}YJsr7{lBdS%m0YLMeWkJ~FG-k1tSQ-(Y)h3QMr>ga~+$m{U6~LffhZFoHmbvL9 zzrKpkx-iJY{7&r4or6# z@V_c7QhctGn@lwVVFNI-Oh<6N1?1y=nh7e0brL35Ay(hg^MA#+CLe|t7lIbRM7HkR zs{sL7g6yB%Tpxd{5C#<%{+7XgPcV^W`!UhPPyZ33Ph)qI*8RaAE9gP*Hy(~ZfZFxx zIexT_#~-zbZKfyTG)Yth|BVX@*P|H@=LTh8#eSOx=oGkD)o2wA@hKYX6d7*5DJa%L zSZmmBAJ7G7RMi=T9GbxHWiLd0iXg}yBk#1b>*Zj9+YLMU?M+7~&=pTyYR~Lo8~^OC zA>Gs36qUhVZeSv*evZ1m)xZvM(o0h;_8CSyf@6_vHvx%AGLYRVr+3r@aI`w1h>=l8 zSq)XfBqCHt4qRaRAfTy>!;-5=;PjNM(m*&r1R>q)ig@YJ);`TJ3B6cyZKY-Z^6Aft ztp&j4{d*op3vYznq49jyL{4?zDd9OhWLwW*<*zWs8x6v47<(KYzzv5L_&c|;{*Xxe!`A-5%f#!&}qF45yqT~jfq51sH zU1P->s6B7jDJMYr~&?4L>+OW8fxHUafCe0BYOp)dic32sK}o)wxDVv zFkjUidDr%6jEs2sG4?vthMzSqIF>%v@ylv6JBSGvq0$2AHBmFQ0nB-%d72(YI8k)u z)mGBB+b3sBjSU4?O`5-^i++~M$uu99?7ORPIHDDKa<_Hy%c=1t39UN=rx_-YaIc+7 zG4YhDLzVyWnJ8UaV7^tm4u6=wW^#AS0r3^Rs|l)>DMN!RaAbg>3<~k3ofznTT`oxe zFcRvKCjud|39Xsgmd+CVj4oCDE72SgBR%OfmcRY*Hj(=Fi%}6{Wth&r|Kv2Am77@K z((v-c*hSHCF6$}Z)uqc1>X0&S0x#&_KJI^TsM0{pw$>+h?+Cwqu&Y)3UUjdq$Yh8I z6uMSduH7~PteZFvxfftHzFy}!T(yxU5Z?`C=^?g@3<* z^Roiz*DJRZjr8ZnfYv4spa1#aZBkR=a!_Ewi~zyJBa?W}qr~sP)FTn0Rg0+Li>aOv z;`B&S;{z>KY#{b4SJ*+~jL%2r0pScM_wqJPe!aFSmP`xW%#W*ZQu{Twy-YJ}-->Vl-(2a>n&AS;k7Ok{jAx3$pQ~7qf05?Ou>$C+uPLF4 zF6;zB9pMs=%ye{f+5qKH4M}uS2@fzo|1<;++tW%aiC%2AQhyVoO^7XDw>wZy|2w}@ z`7+B2(|>S%Q7%I~zoGVwZn%26wxF2!OHDLvIhT27igTg3sCZf~6W~ca`jnbsqFADh zQlzwD&NwZzRxkWT)JCKkOMG7}D=L`Cg8Va7yD<6bwAw!GUbRViBBN$%{lCCje-j_s zyx2Tg9sXH)7XWTE`O18W;WcH6_-GxO!{fZK_e%SZ>J@8NuhmG?ilES!&;Lu>a+DDc zgl}}^E~KOZG&e_B;xeSrCy7jeN6$VoEo^Ev2jframawEs&lFWGu!ILnxNL`qdV~$p zgOW=en4Kj6di0@t)6@_+i;cbeY}w!D#?DcEX^^NSIjsFWt^YXxm9|FvG>iu!_Dr!1 z`cfn~Sj`Zt%Kzg*AKkE&$aocS0w-fw&$r_v(a0)l&OD7xR8Yz22W_eaYhGP@uO~{= zm@ubvhuXM@&+mi#|7kpA(@MV@xep?+}1y!~p;0E}_s3O{}1O^#gNMg?I16 zu*5&vkKXBuFOPok<_BtR&MbS%PXXvR?fYM~$Psd8S6`uRY+S+`EQZWku`|X2{3hl~ zUz`F%id8*yd~H2j!~(4Q8N0DvDwM<4rtP&W1K<*s(FJ~1y(Yt$rQm%|3KEdf65n5z zcMS27)2^T>2JL@y` zfFrSHwWzL5y_EWB3$gm3)KjK7F!fw4ma}fKsfeuDCV%U%UGTm;RLH1tRxtiKv^5lp zX|9omjyv~OmGw&2G~;e0GHdUQQLveudv-k~qu;z79SVie%YXb^Q|y1~2j>rbH8_AG z%A$gS~`tGwhJjjB>)yjp`kFbR{&pVsaD)Vl1>&7>@*5V ziHRdcr&S^N;Hmc6pqpWJX8hAY^fQs|R@6+wkPPS-;mn`{7{EF)i^rNg4!p@b93A;& z&_8|0^mkL&H=IUzd{)A55%Mz=ZDO_=V#XAInL!jwtb1QG8+ZZn1-k-U{c&2C3Lx)n zhVXD$+-7B$vHtU{^lx0+rNOhfrx5{X7K1Z15r21zM`m6ZojSDucowjDpPCrrp3H&` zN=nE%lUA=*pa ze*x$1hl5akdn3n{Zb2kRpRK_Ypx~)fp@66{j|)wNVOG*|2TStj0>Q30*dYoa`U`YM z4w4Knud>mPh}EcWFWwhZ@@-QLV=R>wnAOXlI)*`UXXv&$d5K&Z1w4DdG2%Je)2)wN`}(iEAZ){PA|}Vsi-5+ zAbKpW`<4A@Uz9v`nP1lk26W}WL8G~IC?g~VaTV-;^U+KhV2Jz3I$&DRRYEp)jY*IQ z*?+*SS&konnOJ9n@l!sg^7WGTv3YvFU9=jA^!6hR)L{j@Wjzl+-cj$+4kD}m-t8qn zN128Lx(C-&!+TwYvcG=pC(!=(tAAdvF`!V}<`ujWrYMosaIvEx{8B~RpzGgKH*T)Q zSX+r2+3_6D$`wt$yhfMAIJi_?3@(@J((5^dMZ}6Tx#6|lKj7P&I8%P7_;>#Q9c>tB zjteQwV{$4Ixe-7W<#0OcAz}l<6f@M2TYT_sl0fp*Cg^Kdfm@s7(c@up z7#{PN=zpOYH7-@KvK)O&Vwgz2^XkjaMeDXS?XPO|pEvz?OH5KBanjFLrwE{jp^~J; z;J4|b*173ZryKf%Peb?F!loJw4%5$4Kx0I9%m@7FF5PDo6#^KZZFn*B(sIks>ExhD zl@t7v2V37o~>kR(@9oG|@lSCl|xo}jFYZy>yl zzf!D#E9|G&n?@SvKRhv2G13eiU(iQ%EG0e`8{pz^`6xpVNF<8;k3jI}KVqSYh2fvT zLr1H4^vH*+YIJ)?V#FOOH0tqvISa&sl!DEv5=t`&#b0lC6Z-bHpzH;M(wIetKkU#Y zxodkQD=A>w#MbCaySV<-(-aT+eo@tNsM1>JDy&M}2V;;c?35B^z zOmqj65t-^dYdwAytgUPMV$Xm5>#{?)aofuucX2|k@tGHn_iUfSH+K?B!U--(u3(1lU0@v?y@HsHgOEHYsxmu+L8KJi>4efw1t zms{=sO%L8Qc-UN0H7ECa_uZ01q$bkrW*Gpnl1RwY?|+lW__~b};!EF+j-(4>j?9Le zuYk`17{c@_^=~cWwv?a1c=YN=+1t<+p!&aa*e{3k)fE$_$ID)lq9N&qhKOebag1f; zrON=j3ZsKV)NtB#DvQ?GUijJ}d-K*D!NT=3#-Pk?xx+4YN8g}I@icJ2v}h!sZ7yfL z-8Z~mMSfPjuoI;%QTt!hTu51&rk&GY0;{#SkN=nCL6C zg0?Fy9ps)ec(|3SVDsh=p6YX6^xFDizFhE^>A89Eo zbEl9J_jX)V`M*z|>mTCdp=7>JZ#9>r)HSB)CALt{6?RXS2_cMxu9Fc&(xm|`ILN|f zLaZ5zgmbf{4qlA)gG^7Hq-Y#%yoiRn}KbkD{ldyGb2}mq}emYWGY{j~k*_ z9{vNh{}+#TqLEo?gS9XMTJ8@>Cxd65}1SYuRyesC)*Rv45q{wavFyfSrG zy+|ZC|8bclDp|OOk#;2pxi2&yv+{UKK=o0Ta=RkGDxG3B;e(jqk9k=9$nQcn+A)Wo z)SJzk@EM;LUVN#zl>~iR06};CpC;}GJfm@I`#=Bq%F-fLiQqh4SocHmMHy$yR+7TJ5PtIlVRvj) zsAJ+d*|;fh!bI#7ZA8HNv?1FDBiBW(k~Uqw?8aWCBn214wMWTl2FEqtbidErkrR99W|p zq$CFhB{uc|5^2d?DzW=X*%8zDR~^wQEF|<$#I4Zo`SuTra`%a%Oe*B_#ZAG!ePE6u z!Zn{C_ojHF^`>~>ecnK7PnpImnPs2s5B*3 z0=_UlbF)fbVn*aIaw9>C`R)@})5fn(t}(7DV@ouApNPKwR`Gs*S5v+7mop1WQfcS} zqo2-(jh8g|*m`1~`w7@o>mX}D0ZB?;t+uHL)KeHX{H%XgXKC*MPoHTAD-i*iv9LD zy)UbW1}C^TqWIprkGOuO>EC4VJq=#;8t=(cKj%V9Ba}7)eVXTe8X z?FpK$+Zj>A(LwXHK;qUGQyB8JWd7}%J6>)>DBH00ypQwVH+OJ&k0c%3nt9G8U!Lz> z2^_1q{`(MwK$0-iBN1hjK-wlXz{x$kCSnv=voY3XyEK5Q>O1Ht~lJKs*SICoo=;;?8UOuU`jO+MB24s3244X3x)tnf)sUXJ>obg~W# zxHp2UPu`kyST?P1xN>lD!FZDE>f9=1o6lbS9lDQDQD68DM5hFY4JULa5+LWWFk?Of zOC{Q-qOJ;JMQ1By11RFZO;r{v(RoiurG#(Tm`RU40+^E+Q-jCMGs7Q^G7S;i!T2n4 zmX@W-ZCHK2DF0M8Q$+Qn(WeAfmFjL}R{9g))2FyiJ9;Gc;lnk*3m}*5aDK;CmuJs8 zL@t?b<%*^|iBVp3MTRSq|CX7f9ZQoKoE*n>`|r!dx0Cww_xpdRPxaj=xyG5>dKqNW zZp!nb{#PUN7BYRq=}SG%?s*)nn~`tnmo%QV`Jc{*Kk>(~Dcz1Wx83!`eM6J`anifl z)3yz{V1jpP=Ink_osF5-YRtbX=D&a!8y{~mT){ILlSZwDwb%)}H?Bvi9H7toN*~Od zF5AxnWeNW9=>>;68a^-z4*;vvPkg?JZ>aq>EQc`Y5B{uGkLKxb$ESXGgN>#f26;2S zva3C*5ZGa6Ae%A(LAE^6fWxGMAf-TY6Kr!#iRUl4i7vwWMZNd}r5bl32VuV(Z)v*( zL&5Ru3ob>P(ZNm1x|Y0VC9(VO#J*XKNu>b?PU5PGXVpvq3Zg{`CS;xE`7skFPh1t?Gke<}tr9;AKwg_|Hc78s!F z9XcZ8TVeai6R9T>yb-$j!@;Hj)%T+b-XUS;gRZu=0-LXC{$4opT5j|2S{VOy<~0H| z7M`29Nv92#fvOpg(c@2yiopXfFVrPI2^e+6xtuoM2nQlS>=u}2L`Kdr2L}gxmkxuD zV*!YNq!}Nyb6(%l8vTp*z~Wa)CFCKTtbX3{A*CeL8oHsMvM7k&@wQOkePlr`_Vlxy zW-Z@$nPPQpKTO@SmAVGe(w!=Jc}c0g}S@fAA4y@zBY@LOYBDOhkBpc2W%!Na69L9 zOYJyEYJZ?z*ea8ZP7<_CT4IxgOJ(BMc4q8M{qC0Usi>+x;pTSsf2vlb6|PyanpR$p zPraNqgxvX(M){dPI^W8&)O^^GNw=JEN>h`Ry$*A+BRsHod7}@xnZgk!nj@kFOzH;WnXa+)x2-j3U#Un@=Bsf%-B>#-n@}J2?4=O;&ebD zvkfI>mUgQC8^K4Ii7 zKa}R;_#s>0R+gq#>AW>w0N4K<7Oc7^V9|=^u+>&(;OdG_%%UBz5QR@jOl-KC3|+Hr zpoqm}XkTC{UbLp5Bnc<8=m7EZ@~$NP_&3eHC6*p9+D7h6{yh%KA2!kfU|xN0CQT~C zw?si40m;$!Sv4Q{WJG*JN44vC`m@4S0MJN)VGa&ikHR;cye7q`EG)iWX3Wft?DNZa zvB`WqPv&~hCO)}*ENUKIhqc*2$j@OGr&)?VPJN^?cH5I|Mt#mY?ucwAfn-b@;M9m^(8Cq!mZRbTdl))l*?7oAW-E9fi(_S-m~hah?g;h9QVYZ5q%wwzAh3LRnhm4xU^UIt;LHzJ9## z@N$1rG<)Veb#(BOR`BeIUHNJ}O#b;B!QAS&;#w%*+|4&p`pRk;@2NTo%)Cy24wvV$ z%cvj2b9S%$-7eV^r%;LVgZ`T)&h5(UHiC%utJAqaG1HQ!16=L>i-P^DQ=!Vqsx&If zLBT6R=$vaO@o`-`aJO0T)cJC!rvPD1{=((?PV=tZVN_nfgc_1ER8rwVa=(t`P>SrQ zK9)e%zmL^S?Aw?2k&Pe!t^^)*7MqJ`el5pVqQ7$08af)j_^`AX6F8@O&I@Bz$F@up zxdsEnZY=U0BC$_NXlHt{?CKPO!TR#1u;MCHd7v#$&oexg@`U~Jdk>@SA#?TO{BF~( zb@lzYn-e8!O!zU0uE#@Mq4OH{h>^O^)F08^S`(SYlYCyJ>U*Nvjw|F={*D?vqeFFntiVq+WyBz6x;rP6iL zCK*~G3`HVL#t*M@r`~dNt3Kck`5@@lU>BuKZ;gGN%w?U4Nqn$G@mxG*7HZ@s`FcB? zeOr0dZr-l*8WpbRTy-XB0jKxM+1#p@b=T9$2f&f5xXe1*f{)!^Qe;4^H#Sb2OPbE_ zHuLPzIMfUZdQl#dFtznpUk{%(S-dadKJnl>_42hPG&z2?`h0bV?GZ-Ap!3Av*q5*1 zYvDfghImanv+zV3fM@HA@0ChP71Bd#3)Xf6T#??!eT%HRZxx)VH&&S0dAl!Il zfylqRTUf*&qUeebY!Vn*r3wusY&R5^z8`jbNJMh?3e)?T6P_qr(tHN3_uJymoRfP^ z>6EF%AuTZPk0V$pp4^x&ax97~L}t@)VjucpvF@r`{SsyH=1ROi&rY=3`|cRFT>DO{ z_c=;O_{S;L+tj&@7Zm?)`s{SZhx5RjNt;q6iW}?9eJi3HJ|FHFFWW_OxUFyW>)a7! zeI;B%`+@Yz40%-2w(dK*r0u79(N6B`$Q3xgE5}*&yS0=TI~62QgcAd@$Q<7J#9}wE z&=q1CqX8#;9~7gJvs^vz3SXKyuG0nXOw`{P>)D}OncGz4HLor7?rpd-S5C_3BurftaJG|Cv13+w4zWvVhduex|Z7`;k zvdlFuD|6gUFP24cp*JjZWGswXrt@3jiVdO;yb_|t^t9-mI`E-9*{6s+Y6q=KskIRC zzabD2no3-h(({(38H#KX>IRI7qF8g`V1O@ikMUTbxfaN`CI3ygUfMzh>xZPcx0S<- zA9x|@GLl5TFp0ZSPT_akB=;H@P7Z01*@Mg1$LzN1Sxp^$zN2+IcY_B>@=6{}o|tz- zP?+lIM5cOd8EnB2DvK~xrq3~yE_=ho3m~)C&t4v{nmt15j^cV}7xS%~#|euw^qptD z72fQWpKnesLwPO=M+uz4)eU)9>-XPWWpa@!mIE7=7icerIG+vOIiV1ElD_***YdY5G64sjzmf*UdYtWZbcvt6dU_51tbbbG~mJYkre*UNu=T^R;air!Jgrro!8`$9lAEcGVtx_42@@VxAMO z^WMnIF6Pnu9k=8Bz@7QI8f6XjES&seT*FTPX0DSka)SbXuY&rH2=``+7EqGU|SSNP_n6P`#lyx zhtXwC*-BzO*TmB|Wb10tUP4y#ABqrs7hq+C<;ZS|rAU?(cG_dFJzaAZ1`2L3`e9p} z#w)qi`W%a~Zf~yRi&Tk)aVy^SfJHVr9+#JpFbej%=-2a=rXR2IyiRh7su-x-{pTrF z0xWDa=N$>$1?_UaxNI0RG91WLUX$sC=<~D9o?PS4oHVH(PGTwBZj3!qC_7E2WNP2u z<$itfW@h#CBHdz`&byw|sWz=xWHkMLtZB~pLs(hs)SaImg>JD*_!A*#6dpMb=vs^4 z*W$np?^OqCe2=@lliz%XlG0}!OvrKX;bQfxj!CI56%25EWdffIDSh6_03~_~C)S6S zyO=I17rm*^O)hl$-hr??J-(wix2E~t>4&ghjpEO3^dJ=re}U7P*>yRLz0dWEES!6v}v$8SIZ>WD|>oG;!%;jedetuZL%l))#C*t}Vd5W7>(v1&F zAkVJ)Dv#gRf(h-4hYk=rMnawNVuZa<=_a1TF5Ol0n@T0a+UskibKRF9A*z}NJ}Hpr zn*$hchJKvz+wyKY$gg<+c5LVAx*f;*8A3`=cXHJlzPz$RW>*uEGaj!cw6)nw!tZ%? zeA6cYKOU76z=BjG=9ZX_#bwi}MB4A;&N#;%9VY`21<^lFg)W0AVDkf889VmS^7hHP zVph$uvWv*hl;^-pY~BwDPg^O}t6*W|!S)+%QYI&ry$aOLBpF{wkCv~3Mh7}-4q4uD z^OJa3!Bf3}E=9j-&d@2Q2aQo@l@&bxerU*@@dF~peWWOBOLq`KDTE_*(d=J;)q2AS zaC5XTO?KRJ+;~RM=eI?~s2(pH7>GWUL<+F@QTiF&p#>F6*1X;>k>@uu0N;%I<2(m$ z)gG=S&Zc@SL=sbecAmDtFt80`$5L~h^4l`IIp;Qe;Jho~%yazseW%QjDgY+uq4xPS zaUSC2f_A zjGWQA-NC_^RwVn?W;a`6;uCfmUc2slP4#7m#X@$-^0zc^{^ol3L+XO>#jXU5^bNRQ zWu6eC9#*t^)Y`{cv(N&RdGyIw_~~@sXv20RZOx`AqmrXL|K)iWZ0AZ&dK)x|tMFc?sPe=un}?H(A`h@ZF@1VMzcg#4~iz* zk8}6rq?qY-_@ml6+&P93SaO$YfC5s>!pw&k>TF`7$O$ZGLiK7KmtW!|^1E7~6<){3 z+*+9Bdftc3IeB$%&Rlu=S4X3AUyiwFtf87rr-Q`Cn-5%N&kei4Z$96cFuvHn&9>*0_XAYB%$6&sbyU^2!&z zB=TSWkhY6ovpR<{;ckcVxRi3IZjsBbd&5h8_2gV8snF68P;%N==lyjokN+#NaW(t` zhu?ZNY%zT}Xw>**t5(i6wGrVZe6#M0!9$Q57kWqBJvuNM=dWV)SI@{iPMBjdKmzNl zPPKW{QZ2A0#ovv(Ro6GDSu-FxDK+BAZjlzPx~3sGh)RH^^#q&rL7bSO3D6fCFl62Y zy%%p218$CYT1I3`)Q;~aCmhwMl5sn!Pmk?-^Y1o{s*xBWm`<2_IFUpztgAz>Nh|Q3 z5Mvp)fs|_oz4dC;W$#8CAQXVam*fpdgb znAjIY6p;}#iOJe-oyDeVkAMA&D(1ovxWB z->I&@s2F?|*FCq?Hr}r$C@R*M>Mi*7=ww1Xuk$SNSY?%>dP_bV;dkvQtPpZ9FeuF;%qv#7pm?eLwf2Ys!XR*=rLJGlP* zoJFjYZG6xkp{i?pJ@le?mCk17#IfE@c)1fHz6w!4d_A2RP}3nD$5juxLKffC zjymei;?P!Lc-Ofb$mRBjzZ`IY@ht4)=E^NX2kn`+O@|w@?yoeN3 zdo&}H3l7fb(-HxP;_=fq<4GkN*jwbtrG#_wBN3+Y{y8()bG=iu!fs>Tti+~*&EmYX z_ogk1wpT$-?JkjFLHFoP?cqfI;9IUr?(F2|mhzvjN&(4+j z&1U1~NM^LDFQv<2jhkK8D%`M3u8PG{rbj$YQ(+rLyjjeof*zN~4+hEuL~$QgVB>gh zd7HXxdg3`uj2Y!)w)}o)?KXj@3E>T4WrR)(!vS{YA%XWDksQVLe)&?{n|F zzBic9vRMr|K7Qn!cWCUeX}*FqURh3ZI+>aQeXr%HM%Fre)NdjJPv^q)12N6TxT6K# zFzM!PDG!|IM3YoJt|$N{KYP7D4S@@AS*(itY!J`s`D2)#XFY~p=IoezuGJ*&a$4pw zC(&h&4r;K`QA7u*&f(RoSM{Eye;++SnvzP6ideL?ZX{r&n22O++EwVy^{W6BX}n@^ zIa&9`^pf8L^=j0$kh-(_A(?2 z8wzVkb>G7QEUB&?76;B5NSYUM)~+b=p$L9nqOQm8w}n&%dbR8BWvD)#8&^>@2z)tu zh1|Dp36*bnecLwC_MRQz+=exN_`V75!=@Q}jfG6KrAv7j3YUEum~f8nUUw?19x<8P zbrjdMB-A)K;&n+qGbDDW{qgb(`hge9U3f+f7D<1x}Xu zd-qp}I*mZfGw_b=0K(N7`L;)x11wmn(l&y2K)3Rb&l?hBeMzASyDL3tQ{2YdTn{y) zorNdbz~QkHv(*9?>sMiqS>upUzzuj#-F9}Lm}m8+eH*6o$(hHb>4;cgGB;(#YFBTr zK3;csa^kZjo;4fm2l}^2eM7FiwsXz3@~F-zl|cUG0A_hr34Gp#To7P^SYOMCC=H#h z>+9|PTGsg}JnrUq2T-p_{Q95lHK4Fwi+mjS79-@o?n#K$k-KWY8L zsgs4ZWOB)UZrs7p9e<4zt<5znFCX=AH$H;1q}fl>6H{uAW@)#IK3k@q+~TXm|L}Dc zP*HAOTM?y2O6f)#1f*NKySuwPh7hEryOHkh7U`DmZWy}zfAM}d|GVy5vu2GhojLD0 zJD&aQI3p_AQ}g1fWWSf4e9w6U{7N+-Q=ob0Qwx^6Eq~n(XfyYbh9$pOo_hrzwOkFx z(bvkQdL_?az(&MQ(!1NXzW4$6_relMWT1Q%I=VRO=d_(P!zI-Cz{6_?!VXJy4L@aJ zg=rwu^|fjwvl#JSH(rN-TCaq8lCy+E%i|E6e7MS4J9eW{Rcz zio6#2a2n<)#ITmuU2C zZq8y#U&He*FjrbbPS0vK&%o(&Y9{K)Inn4tsYY!{Wn*#e0+1XU1Up$At$w9t6`#N; zDJwH0$X?K3sg;xD8ez>XEJ-!wA5*pYaoo*zzK?chl<8nKk5Eo_SE#hyT}a!ptE9=KYaTcJg+K`V%f6Kxs!99TtFj)vx4)A@ z-X46~Jr5-d(Ahqdnpxf)oJ1?pPU1$LE{@Fna)k&z;2CZ!~IQ`4#D&KK_--x z`&9Q`liY!Sl4-Y)A4PSl-Fvi-`|OnOrc;!imn4*LdN`FYFWipeqJ!ofB7J}02DJ%c z`;ENQ@IH>y@V9xV5g0+5=JT2J;tP-lY$>(Cqc&sb{Z>>oZ&E#HDVI{A0sTcS$Z`KB zL}PPv^HcXs;=}#Ht#XyKNKy%egoMTJY@spd;^t**O?1~=CaFl8Ld4ZMw85nxOUVoL zC-yR$c5^kH<$np2ZkV61B~$Cs;`r<+i+Ag@F^$nBhECWIT&-n!Pq8;RPRo;4kG&5d=~jtS~~nNc@Cx?mEU9e4Jb6+$&3^)dFGF zbj@_Zy=~NmFk^yBo0XHZI%`()(Trk~>*gJ)c2_X%$nuEhtDTXPr}tAuNFUNH~&Tt$S_plRi zeBL>hn+6IM!UaJ%E!nk>g}y}IriC2;l5M%d;r=*RDgAKV9q@_}$Txl1Ejs;hJGwmsZ_5<&S{wKIuEFQCi^fS~mvt;o}xxH=P=#9|F$q_v_{Mu%k`2Lx6kJ z9-OUye>1#zdp|z2nDV8ge3Jdq<6UX-XLof*=MZ|lY-23Apw{Ix^ zdgbvLnLEzsGp$@S;4TfJ+4b2Z;5fr=h0X#jAN-JgM|K$}QZuFHy44To=w zoDW#X-MJBwJfX>7R7#gUYLeYdd_jLqGC_AbRzL@Jy+p5DA`r%+$EFE$GSh?zTM&Xq zMGLVnSwEz`YsYA%rlet7t9eSjR5mxl8l^Zi0OK56Sr&scl}gmV0CxbbNl87v^uGgJ z8@cU$T4f&Ddbs#}&6Kxf&v<;RWv2R_00mAuegs?PW||x155-O1hV!TrbgE_UNVWu$ ze_ewSJyP@HS4;oz#g0`3-}LBkqIRamyN%ft$LNwm7wqA4^;mJncBUn}o!KVG=+Z*( z?cwwEcyUmE72N<&zkCe{#=!A8(N*U=ji0OPj!PCw^ES8Co1I>kbq{_?5|$&zoRnLA z{^y=eXRttmRi8@}4`f~`X17WccXtDU?XZ5M^=#VW7tjoieM&mi@v71CKh-1|PiEn@ z#R(fXhKM{m^+*jqP{>bZL0o|@XA1i@_SqcX<>H|^0_hDCNxU@oE1LI`=C37UqoW}a z{Fy9nBqWmn`n8wbNxtsU+dsYD!SrxTz^Et9wNJ$Pz{->Pv)5PJ=B9H?LygYmKw7I= ziw;rbZ9d41RePE9g{gSXec6vxv%Y| z_q%sm>^R$3SHWY&A~lj5Zz;&4xECE6Xd14VHv=x`Z=ZbxGLVg%1s4S>LVp4yK>)R=Q@3lmO;c>#8B*gwDjuZa&6>`2s zUOzNJ+jd3jHUE9Zm%J2aIL6fg4I;gkS9H+`Mfs6;NEC+de()oln>`Fpp`q6~;D9O} zq7}(whvPi+Uv<1mlHaGxQ!fhv+ta$lV`w;s(Qs3KU882{8)S?!7C$23{7`RX-FDsj zabjmDRxWNqP^0+q^dJcb)=J^1d8y@gy3xK4eDI)(S9E^8cL8M8;cDkOG`>oX#*w;# zTaIZZ+_~^1+0XTJTN#Gm(B*Wm6*<*>BlK>)yB6ubo?WzRw8-s&ORc#)1{nRCr1*^$ zZtkK^S2xPbCAW7^)o~U~CR&G0*QRjH4vixVPK$osxGvwD^egs|<95eECxP9hisj-E zpu{IGqZ+R%1doOr3gIh%FwS##AG;45o40hUR}AD`2V+iY@BTR99BKa1mp4Z!y++pcbwlYlfUdVMR~IXm}lZ@03o)W+IvweIhH ze(;tuwfU5bj$NNAWNV}57St!%aK1L*4(;uQIA*O)XrtQ(^nkpqvzacK@oU`|Jg@~9eZ-zN?e z(6ji~iEUQ=Wvy?y6|IZvM6IUOeD}WPL1w1o1y}dM2k6HZZHk~1xqS+w{GsV3jcXKh z?r1-b*Qjs*%xq{A!EE!Z{?8k)(KZeRAKMq@-eBR}?x0I|e`b3>UY;I`Do)ZxV0AMN3F9FS=vldaT=w4Jt8kwdKhS>hv?^ zST)nKwQD9cEDX{LA>WQNMdg6?3*_H`N}Iw>Xcs`k_jPL}Zi6|@T92gmlWux?M6ooK zOjF#JU}a)h$k{!jqG;_ozcMLgGI^4_LxuU;#v($O@AV{K|Y>tBD<}j?!;;{I^7QIU@Z1m zY&uS2Spany9UG%_^o^I$_CQ4vRzX2QxuI&BC17h^Uynxz7@{GVUb%Kl-4@pU85TTL3Mnv<%P!Ez2_)JD` zMa0U?uu^3xEG3c$!dse*cu6R(kGWD7Nd&RG2Z?Ce7NfPuS1~D9SzY~e!;LFL=m8iQ zINZi`g*ADL6Az&FR;9h&#Im{p#L~Gh$1g_1qh=jXoNnDJVt*$x0ioB{gMK1_rJK+v zcH{3e`9&hj(>+aK2%p=CL`MTWW6{1N|G`irky4kR3QDbjsAbExV!rugq95D&jfWPH<8J%aqz~6&TeZ->{ORX= zr7e&S>1MPfHI*-C_N(=9fYfz2qfs&3|{~OA-?mXLuuAiIC&7mi}Ta1z%`W~o} z&36eP=@U?XUIxTkU2j=$06d93wFdw;ovD1_{>rrzeBz(9FnR1^2CSP)j0k3n?r0Hy zAJltAdY0U*#9Iy|vk=hYuFhFzF2yvP{`0zvZ7&{iLfco9#e&s!sR|EPuYiVofYpvA zoJD0^`U&DY32$zv>50knt)Dw2^h1wY9_-usCiJVF?vI+;Umv#NAnhS6XTw+CZynyC zj300!PH^8LDloM24_-dtRiV%|v9q!Z&Jeg!}rI2suvd_gMh6ZO5d^ zuvQiCNJ#oq4jzwg`%T0Se`(pc|_Mt6zLj^k%YgEk4KtXaH_7*`oR8%0ES0e1tq^$Mk@u!& z#QIkDmJC7j?eC%b?+7uRM+nkh*YaU#^)sgn6zaqJvxM=&AK+5y^L_X$F~v;F3*C=Y z>Yq;@Jp!5*E(9M++z6cfHOL1Jpedf_#MvhRo1q~%d5$w#qA~R;nA6Z6DHXISQpcPr zX894h4FF53$zUs*Ms$Ci8&B%pI$&tnPfp-6GS3pr5%qzF1LOo1W~dvP?etpKC5H8c9g;X4@Vh}>{~(rsX&ajiv)K=Q0M~eZUbqy9fv#knm5mWU zvrtz3d~@AttSqbBmFVIIHkw^O_<+{(+=qXPuiN|q5_oiTOz*7tEQ!6(ZdL)``(g@@ z+QTZ#EH%h4=JlAxlUa258qH5Gq{(~}mOx=I;ocH(b0gmFH!=hDm(0^vKxHBY1%-Gc z5|JMfV~iy-mT%Xq`&1tJhgOB5I|#cRjrWLFlyAO11JZC^_ZO=0+`IbD^z^r!L=b;7 z!haWVd>~n3TtFre;~Q7<2FbA#9!Zy$Mo|9CG;-hvy*uUg!Ac(raa|cqABR z$mqF0v&n$ze1Z&VC?7`RM5n&FPKvL^Y8-Fm=4sVU2f12h(1v_^NWCQh=41eR_Bs0Q z`F%1vZEG#kKgM5aks=Yz%IR$^hcfAL^>%Z?77fCT@_EAQDpvGY zi<|}T=eOAKPNu4*t%90=KihwtIRGBh8!*QQ?w=c^d3v2lJ?eq5t%5Lxz`@6Q1OCVE zFyz1t?o*p&ym!o7``Sx?gpvRI03>7sjEW^86m=XsmC_Odzn{a!;qL}>c4ug(`AFAI z@%Ahlx;Zmc-r&B_lu087nlFbNih&s@|LeWl7JwuS@u2eDp;f+H-iKDaG4MkQ=Q3o; znRn*4b(%*jS&!DVXXH@$ohA9lq5S&ebOj`##Pf0L)UYQ_st8*W7%aj=GJ)=IoFL8$ zqehOaxDTOp9I9b&SHh<;K-IOH!Rp8agzRq{!J|cl{{zfZ4_n##rNKaH;7T}yftv3l z(0#Dr1KzLUTWRtCwoD3zZwKbDlXC}!JS)u&dm1lov>^SfC1-gC__{M>2pt=9;PSl% z<%e2sBA`2q7!k0bHPaV zs4@6K-)#NDgvcNNk@PkxY^k0d46C)m16y7T-d`E{6R!PF%nnhcbsT5dBh zOJU2jDj~{{!b4(wL*twuj=cC}%DP(~hZkMG3(2_K+-3VOx`}O1_M%$U@ zDbMu6cN9QEZF~^mMJ0!&$bcY(h7BNVcKUQk0%P)cEfGJsX&X0B61N_Cx40DrJ^+KG z4~Gu+=Rl{a>y%m|cX#)8+$a|xgpj}S)>x%5Vd~#bUTd2HOLb52daYxtUL)?T7)ljy z!HTuP**jVJ;_J;aNPY{3T1h-; zY5bGFKaB?nrB|thklQ);TQ}tYml`YNpD2Eac+qm6rO|7iRFQI?G*Nl&xejR8h0zg_ z)RwXI7FH3uN*c7h0zs~orm+GLngl#P=B3(assw$xl)r_t-*F(Ep&RY3)688T=+G+k zvpa-3#duntkvj=7=ihHD!_dfx3Jk0Vvp6Z!|D*KzuV>A(NErSGi}KwCI6PDAUEhe- zW`Dgz(mDI&_a6kZRV(L89AVXwcQNf4-XE+G5H9`-#D1N0MaVM_t*ugNl~4WAQ5gs& zQ79C$QK9Qq7gqIEmwDJ6C)uM~Qz8jTR&n&jY@%&Pn5*xEqx#L+b&BF4-IJdkzUK1y zJk0^@(Gq_6n|GvJH5SnbdU&yRST(|*#6Lr#!bg_1AqrP}BZ^3;6T&C$VC4oC|A&P< zqJxMVPL7l_dyH)79*jZhkL%f3+v?<=mV#x@BhQ|*j~u18iv3Z&O9_R34Jz6&fBpZ| zfJYO584sQKW#Q!bNMg`3@B}xUy1l3+f zeusE@ii>&?{}*Wco9_JOeH7RfJkocU2a!ZyJ)?=>Hv6sz=ZG~~8==Y7_(hqlC=KS8 z-glNX%6tln6VD_*_#4muo9ucIka`9F=!}j7-^CQd!dHgf-83gEHz{X?CC3mg4aa?L ztPz<}YY?5ONy+9>W;{Mc?70&xe+BdbVDovsnql3PFHZ*^XNDJ_hE0@P-2!9~&5y%L z6p0^M>TZ+I;P^S(a#7R8yf+SKQ1?%M@1GVLaK+1Gkh-)Q(F}W2ed*T>8&_6vBsbfv zFwh9$x>J*J^f(9M^nH|$-W0oQ4$rtXZ_fht*Zyf$@DY)}cdXDCvzwI8d@*GXCxUB@ zvcqEPnR%=c9giTlwHcPow|0{vcU9nn8PEd$weHiUb;(G8{xeXB|GN1}0H5Y05}b6M z08TtfROiAW_wXQmX{s1;Ln|H&s9fnMQ@`-PwB-EFJpZOQUN5}!)`T{$P6TYX8!;%V zPF2rK7$sdgX(+PQoWgDUqLgLMJs9((b^J5y{_WzD7QSaF0dR`Nkiun;CQAR7$^z6PX$@Up!;55vMcznR-e8WM&6S*hwfa@75 z?(bo2mkaZe-3}_Q@*52z%t~Wl4NFCSnlR1Z$Jestn)?rE$pfJxg-^gsb1+AZ1h*;N z(NwzeW9Y@MMnM{COG9k*p1YE+u#t1;#pUo#O}XIzw_(V_P|wB5XeP2^)=Q;DV11S1 z+PQ~fPm^l0Jpb4*}8FyvUQ<1_&BIwuyoEpfde3! zJfQ?$fn5fw4&m+wePYJ-u(t9N!l6Md#qd=|eH&w>S+<7+vUjtBeb;)zp*tv8K<;^& z6F7_uT(MXHH;4Pc5O;L;)l*~Xw@)M4T8=4-1c-!teda~x(yx=pIr;{PMw8*X73bsD zlk;DrD7-FVIs`N$qs$b07I*M^^3f=XX(%LNCkqHS4!4Om*cS<2Qus6IS6-G^^8Y`n z@-`>*g6S5(QYQsGpNR0z3G(p*e0>=x4g2=oD6rX{clCC$G?V}3dViV(wSM)JSrPzj z)QmvtIl%B=!FylD_uJZ@<5ld`3vG-pLW=~Tz|cf!nQ~nx%WuzXK)|7%CDc?9{EKn= zBQRg4gwzfOxo^nM++H`@x}Ia6TQc$nsmlpbTw)R$%-TnWBWJs3=bQg=Kfzy|sdJcD zS{iDetOCW-gc4wp!|$~`DYho9BBJ_Z#oXniJGwiB^WPWy3eGI@4Mhs$lfHpYu0GmI z{wZ1Wt5S>J-;2KM_1&cu%#CB>RZ7UH12O6_?babCRUw~P0F_n*>v@Iz)21ECKnTF0 zMJBH3$Y#5{;8_qP0a^HPIcRVg3)S4kK?K9r&{p*O%DCyhlB^j)V%JD{TB!6MGBcW?E0zS z>C`WpjCzA@p1}JHY=6rRUT*@U*~Yk5AqfGOCIGv#)+PGL*gvKnI(kt9R`-a)+v@;y z%e6IutODFg3|N6T5FR5k$W>rcnAFGWtCZHFABI81(UdeJAb&CU!5cz~4(MMf=LFL` zuRm_%=ZKyxnWqPNMsOwh)8U2VLR>jFo8G$uV@QUTe+`rQL#2B7A;$F>kSr+#y0tov@bKe@#_k2)E=6?S3+#?PdK!jKPvIC3@#Z|n%)^11?a|aV zvKyV^9mIW>aeHBQ+f}b@nW;qeAQV9;3Sjb^M6~Bpn=3r#nA$4noAtK_dB1B$dA)=F z&cL)@pjw@!=!~xTYd`*w-f(irylz9-NqIPlfUqbAtf}4>TJFd(&*IN%aO63`h z#3WYcyu(`gqid2{q+V{Y>!#VmghAMU$&Uc$mHz9q^O*s{B+iXj>;0uoI<@jc_~|5t z!m@p0O!k|gbUYDl@6WQ}M6Bp;uou__+YDf%dgvjlSO)0Fivoaawn?FhiG|0Hi7GZG zWNgpkz92i1E8h9sXUosk$U2P|23C$XIeOG%)2bvS)r~Bt?%tAG?Nb zCSZP_Lbl#76ZW6mQ`xPgy| z4B5e$6AMrgXF~SEWB-3&qVMa))ThX1JKqV{C$dh=TC3wfnan%#Wm4sW=2%wdQfY@sKc7=)^0RA>l_Jmtp{{Ud#{3 z{uiM0$HIANh~Kh$*e(UzDj7S7>Rgb1WFh>pI(r?zNB$|eP}br52TVQE^i|CN+FBM8YsY?9*1LA|`l{P+kZ)f{RNyoU z&p6hKT92$so-+JV5c?O5eM0ekyYFX0Iy;}g9}PkZW&R~0 z9zUDU_<{Mv1Bhw@h&#Tn7b?qQHa&RD*A=sK)>=pZ=k{SjW=P@2>9tZvkC`d%BzIyh z5pP)Syua>O5?>SkSIpid@{Ena-e~*ho9*$R#p!x-fKJ+yKF8GG8anOM1iU{PM0p%d zU#iJr|K?U&_k4rlz1vdc2bQ2^qWusHU3-p`rBU$`|x~nZ%Te}s>Xi2 z2Yl-rqU-iPazrgB(UsZri3kr9?7@Y9@sr_7FjpoE7;GQyO`cXJ_1GxL8ZD1Y^6Mx= z0lBkVAUE&_R?7p#$R;yvHcbG|_UlLvL~iBbCZEhpS7$dVKsEa*edpr?6ZBu9k1#$0 z#0Y6ks0Xz<7!$*75?Mc$d z8;x&fzxEFAY42L>`fww77T<@5|vG|`jCkb-MQj<1!vMBtjA4c|@YhASQsOm{f;qvClz`x;cm!xO*#@nMm^V8M% zy8TKd0FI#t^kiLbhsfRdAzWgg{cusAuH<_F+2>Dw=1Vwq>J(taQ(lYtr5qTpl zEpvDG;)Dv%@z=$h|9tY_H-dxUjoV67^2||~`h2(}_|v~t zLj0!TJc}gX{<<`Tlq3Kshc`kWg{T~`rGXJ()>R;2%FAzb3>Gq9tdAEkJ{dmmFQ2n! zk4Up7GuMdgoJGzfzS9n$=yd~zt z>vH7Ftb;ljk?BCa0q- zpIL}D&*vr};GHbKm727gj;B6vEU@oVV#r=pK*$!@OUmv~;auM}!`icXhlNFHd^%gb zr{CTs(feAf+BJlcDcAE_p#tQhLv%3;jAJ?1m^oQxKn9&9p9~Pn)@d@<8;;78PgF66 zl%M{<*T(zvtnlMd>WVVjuvuN@SI6O4|LzaQsoTC?_>ZrInvpWjQ5dID8%3HB-MSUP<)lmMqUf>W;Hd_vcD( z3;IPm-1PAAC+wN_sCGghaACaJ2xCy4gfm+%*_(cg?1&z9f8 zFFVEwc}J^R7jA0x8kd8(l~%3fF%*|Q)>QKV7(J3yYgvg|f05=e>8hzZQ)f~+p>f*~ z6OTa2U_^qUvczs5UZmW@Ut@kJ6nlU16*8|370V*EoY`t75`p?Gonpc_w1>zau+{z> z%LB9|7w*AV{#RlNk}2y?#@hRdPekA5Loj@@@_)SOzkUxyA>F9W?yqWT(CZ!=D0nZ{ z&*`umU1dJTtLd_jz-v#`XujB_;KzBEH$Ue2A*5noyY8obyGazk8Oaq%!~|?dD?B)>)H{e{HTD{0I&O*2cZe0cC!JB+ANxq)|5{+Z zp{0I|Kzu-Od}p(GwlONjMHs&usb_Dhu2xFfGN5Fkb_pM}#HVk=;yTcajASz%Xm1W}Z@Ik)#5&&dd|rxQ>$lV!CZa-_YoqXH zt0Jk@YI+%n(yaI5=VMK@AKmoFHV2Whu?azk2m2@sbJcEP6QM|m2vLzFV%z(xonQAh z!rNZxZIIqcu~YN7>e55-^Vdgv3jp00zq zUeHp>@TUm!K(q+pYhrxr5)#@Iy!Kz03#I$yUg&KOcp7Vn_n&ARRz!RkrMOZk0$%Nr zkxHf7i}xMR`S{J#w$i9(+?KoVl*-EObi0TQC36)LZRnmbkvJj8GrE-wB;FURr2s|d zy}B(pjSf7od)CdSt_U4kueYOyKh~%FKndSoSlB)5%zB@=JuBRsKTy=&~80`U`wxQ%CqQr{!X$3|rOqd`Mq!Y+8a)|Gamry$`+9dfN zB`lJYzK`TlME0^oz`;WHWL3S_80yno z_1a?O2URgcao^q3*e5{?IGk^<1HO@M%7TV917pMvQyCai4Mb1s@0gsgq5OmwcL$5!yq6?jDQ^; zAB?gsWMsTf6M1VUT=0|w6;bR{F&GtV^?Sm-WosoZ@Qf9PtbRP)L)ou0JGt7bxJ(R+ ztPaH=SDRrYts!yZ+RhcH*dkljFovP9cpfw{I?D0U*^JJe46QR)-;0=DpPX|rb)Ud zsP0V_+Ou<3)ryqq#(eer#o}m0%*~TeU~%-DeR-!d+Wo_XAMUQR6#X|xJz=sATd*RU!PY3#CFE-~$ zK6pM)vtY;ig=j+|TN2o{31HzbpM%^)w?g+h*!&WnTsD3w@^qt9+G`8=`!{To zGZop@l7^2zu`n?5n<6?*`SUrg+O^qeXf!#)po~*GKAg+@f9PhV*^jXM=E<^4@sr4^ zp}hR!b&W^6V0U}H#Gkd337@=N&2zK|k-pqOL8)n$uVoTZTg|X$9Gervtjj|D2b2X;LK$5r{zSml2}6t%h5rJa7dL( z!{Q>%)7r%@2L7~`7wf~^v7$Sp*|wr_6;&w*^S}+-yhT(>$UMXp+tY6zwKu5McK&Cs zzgH{RVS;>h%tK}o>`S(~Lf;M`yKYo7%VINr^VD)VzP9PpW+&@x8Aq00G(&mc*LVnu zC&c1_ZspvOFqz8%u+s+?5coKP&E2j7M~P_}<2tY#R|eLtAGPsOfuZOSv`nx^;@2x( zYiUtmzzeF}xv-tsWu)JnIbPi*x~5KHgGLRm3ho#y_?hfeb#h;AoA2xYrT1XLElZ`J z|3!%o;v%VDH%BJoAo%opnESEsz8zPx?On_zctj#3Vk^sfOorq*F2RF77nVn2?C zWz@T_FoiX<&jVMxSj|{l>r-i-A5=J1hwcn(I3DzMTXQ`hOe&=L(78`r9@}7%^l0nc z>uqfxL44~iZcuYkB+dK2I%gn6F5PPJ&+O^1 zdv*hPx##-+sO%tO0?99jtXKEU6>EdX$RG|IWZ{Q0dRePGHQ5XqI~Zu26Tcy$*&)Lx z1ntED;dY5*9SfG3-EEy3!Ji}29RTh)4SxsY&S_WEbo=1%I$EapNT-9gnA6S4E-LlG zV{NdPexn)Dp2>LwlcTJ4jlfjaC`-OrMk<$&bfLpZhs_o(z2)PpjKa&)~jY7}48b;y8dKN5yG{ z>_t5q;EyXldEG7)+B0oKyS*K3ZGAn|cxZ-|tPf1bgQ>GSB&0y@A$z_(`Lmqh`AgVQ z7z07?6K7-~ExN=K0#Pn$_XvX#90YV3h0R zXA-LjpII>0mq!yQu zgx|>RDRtp-7ut~=g3RrZk6NI{x7&JDgPLy_b5+In(K+6m16iNYTAIypFkd~lJ64>+&W1Z=@h7tG zL4D$_Uz&xIeathqfuTu7&!@lXfT?$v#gHm64yK3}3pM7(5`k#>^gRgxphy$Ygg<68 zOMp95f4Z!#tvT518R0stpi;829pA<;s36a}?8s*1a-rzFHF1k!9!#N#JSInjsT0i> zwY@)|G6Bt20eQs{1EiO*f)W9-YWcFAs58sP{XH%Q(YiN=VaaBMsxKk0#JnMfGP5(d z^Wc!;+8|TgkzUTIEXkx*_S6~;C6A0GraQf(P?p}EC?vAB-^i~+$?jK40I+Y5Ur5sW zc)px$wyi_f>g59iFeo|2+9r!mGjpa!yXY`O$;@`G z&rr}!S26u1gk~xXHh{JqQMtwx&bwfI z&dboME}R>GJ1_U}@bG2SOQmE6DWbl;AIW!>Ldb})u;MmpRdzpCR)DljqoM?5BI_vr z1)X85X0k?YSs-iiK{>)MDO-au74I3Re*a|g=uv~&Sn%sm;WPH}`u1k7Vz;WsOUSX% zvt%W^B2Zu+B8ya+LxE;-VoTWEWvYxp%E1OF7r60o9NS~7V}jqgoK3lXZ`dBeLajy%)&M}fJLD<04BEY5PmzjePSZ{ zzS;3z<~$)oTnJ6No>!qj16C~50bW7-_ASo-DdZsq~yg(&GACR(Evf z)a;e?oA%2^Br;=X=e8F=j{Nb)Homi5)XZ5Tp=|MAL@)7v9KU$zFa5fat)%I+ zJEQV$c@=N=9vq*W?KqeyE5`XvK2KVcG9C%ZKieqH86lEQMU??BC4ET%>n#UGB)Q*TQ0Ed9I3k z;)?xe z!noa)EL)2!xn9#c2!`P1@{N7Re|Wg{yHPf#JAY<-6K$S!mjU#Vl9#{J?V#R`T%hV9XsvjekVvEBE)oODKdm5_EVEexPMmS|jK8qro zt1&4)r*psST<3@W!LT?EVnxPX+wYQ5(E>ftP9naJHW$mv4Dx@X@m-gyGtr(GLtU$pm%j|NI z?Qys-ecW@8x$l(rJ;;duWt;US9GdrJLfg&(r`tv#X__QbH5wc1duDDn-8%cj86^zC zgNl~HjCnJx_aMF+pdNGk5NZ`0LiVa3sw)}W=?^_3pcdOj&`b&Z_bF|lY|Gq!uKV26Qtk0Yux zGpEx-vR=iaq*RvS?RCoa#K#06h&|t**X&iZYIzTGy{w8n0-Y&saKIgk2E*4g*KbW& zs6C7=O_t*=O=&qFE98PqXV(Q?PD7NUKv=c4a7)d#1wB7#TkaASmH_82$3Mule?)Am zGS%p+asgGS_)vmlonTvLKKJl;PmQ{(HM5)sj1o++7PKLDcD2;tkc8{mRnn%3`~Ha4~ z@rPLN0c8&~(cxu|xZ@2cN3j|9VKoN^gNer4PT&vDjRnMYpz(k7Uioy&cEfjtFIQ#; zkUNqzk2?=oJ#mEo-qy2ucJP|z2rYNc2T?&rXC;?goCSxFGM$7wMO}GU^jKh${h~-^ zF)=#h8ZM&0Z+PQ`1DA}(;T!ZXQb`Xn9IUp{i#3lv)I;kcC|N*2rdZK9wNH4?{<1qD z+~1G$+rD+#YyZIW(iYsp8`XBkEpctsyRMF22q>@6RWR;;FK1hHTzI z5ym<}C`1r`C!Mq6cel%yd#F9#oF+~gp`wni2qK}4**z4`OC9#Jn?iCNuSEv!fEuDt z4}7;y?-^z-=TR2r^?DQH0}@i_8s{7IA((W(U@ z1^YG5dld569LXQ?z;5JdG%~qP*1CM~Hac+ghp!5nt29chPEAE4v)eAbNAzp!LdQbv zk>kE6n@DI6J$F5I_n_Ms+xyaYe~BRD*UCqgog|}CS@zNMh@Z&X1(AL$N?T4j=WZdbwKZx_hwo$P+NN1{q^rF5&P3sv`qBOAK!SA z&(&9|-{1JleiLQH)HAvj(R~5nKzdQ_WzObN4SvB;38!q1@Fz~u7XP_;4GzmPu8FOj zUOzh4g0X%3xvfy#oPF3b+KU^MEUhKt(kbq{t0+l^$K~uUcYCwRqClQY#z+~QAJKZT z664*yX`Z6=4_)1E{Nbkda&Y&$SPigTvfm3~0M7My-m)TyN6>yG7&}SfUXODK<|^N5 z?V3_C;%87Fd8lolo6RLteVu3N>3}$3NUcSm`58O%DV`R?yt4VQ>Yzj@AFZv&zqN~w zt~UGfb>V1aKOLQ9rF~uYS6fHM+0lgkgynSmbp}1Kh%4wgGTT;eOmWgl$?etlQamIA zsjz3Uss)I>YKv}9W>>A8!Fx)sQ5(6EQqO#ykAL}jA3-Fg_rX$;fLdukUV2bs){-O#?O`AfNVH9FSA~5PtXK*fSCXUl> zX>A-G%LNzYp4D{eF?#8Qjy2a^2J}bZmJU%uzViKG&IE#ZfxdyEQhq|aGt-!M!DKNC z?)S%a`Q*3AOf`5jKxZv&Xaw2r*}lNf^>7_0z;?S|OUhRKqw9oQF`n=Y88?HjB;;F) zqqmaIsU~#PIvvJyTphXxaM$!j@BLiu;ZF|mhJIJWn!};8(15|#)D=T!SAm^P*w`&> zJQs_*Z!%|``zJ5H}=KPCoHGV z<{m!lf8U{k>xRjJbGaR3-_p1^BcSO?-3xtT!+70k8EnyNX+y0;h`=Gw9yMN~=GM{n zlAF5fb@!ncQq!$(t*6mwlY$#?5_S}nY(Hp6~9@|mlEtWJMH*fhe2}SKYPlM+naCC{;W@T`;}Wod|ryK z-}qxBe{FEGBm|2|WiP)NAh&+XCNCcs+V9AcS6qT4wg=(a=NX9s6|GW`tlIz5QDYIv zT{6uI5FnINh9%Jo>9oN--lsX=UpTdT^A!=cCO;&|`6<3aR2;SAS_zzih9|^+DR}4u zg-{kb*d7{VZIJC!nG-6a(hvgk9Ei$C9W-0OH|ZZ5=S=)RtIPe^_O}o}oDL#DTc7y-`(vMTi&{r|5qdXEU3-$KGGUj`^tNI9 zd_f|1HTFvW)*Nr~)VXfKaFjC-bcliMP6y+7!A0=uf0mYeQ{e+B2oC?&80}@dJaO-? zgZrnchBTOItNQ|e9 zpfWf0U8e!-&-$f=yBzbGt1#@4>B2c{y){8a4}LF4p*Puk6LDJMR$Bwn5_?m-9+`(n z;pQFuwoG%{R~12{@ZL7lwUw=t``ot1VRrxnb)i}4#CB~&$mn_9`M7?l;Mud{)9BEA z6bo;p`3609UnwFn1qObzE7V1h$x0Z^+_et3)~%|t66L$kGflb$ZaH zqr!UShwBvSW0ENb6Vc?GfioN4+nlDSqyD10&{+^ar08zB;*&XQe1SI zy9rG(nqc%+*_?guFR1r`-pVuv708G%f)qB#veCEH4}+@ReWFk=z)NxW5$2Ceru5zs zsSAxe3jDGRUDMlp-pz9_ad!|8<_M0??yrsT#DHLPP{)#*RwF1HXu{0BYP8>pRO@z2 zgqgxm4%wfnR|(?`=G7C2(HoUWisaaCa0|&qNDanNvJkuvm8qkXv`MAgOky<4K>R{L zmSNq9d+7mt<-+J|U=C^huR zjIv$=py2!F19TZ&J=p!FR->d%vpybvmqxlGky_dnV~DOf!=@iHFAvp5As+!=3U%V$pF@01(*XRy}* zfP}55<*K?w%y^+ajmXPwefWy`4tJ%t=Yc(!q5hgS^HNr6qUo|tXtHEe0;QCISo@@N zEHicD_QUIyK^#5pxy?sNB(wpL&ROMJhj_9V9oze#&U>ugrplO+)>laXD=>I zPT4~?oa|a79`2F%JDO|`MKiDGB_LGexJo^ofC`Fl022BYh0;I-N~t7_lRD@5jY1Kr zaX|mLnszRBRM==~zAe&VEKsVP+^75k_ii+Z++!Yx&t#dvv0OGo@u6B&TR-UL$B%+K zd1odoNm=3oKmVD+-Xm9e`RLb~)i!H}#YeGZGU^yI3gx(>^y=Px&!xL=5V1{T5Cuvt zQ)XY+kG3YHp4N{s$yJDM^hr|IQjWS^9w@C?CL8uwbV!(r-_>cS<8o^U9sBqnGUTFY zaplSi3do5|kPXDrm z(-wSX<4wS1Pv3}ZEXp^IDL$G4P=5P3(3)Dol5Cfa*KAmtvyR}Oi`cr<&DnfBk9DUd zi=PoO-uOxgKpU91Ubc1562Wr`x1GXrWh}oS`x{OH3Q3Cy_tnn7t0|?=BCL0ek{~-= z`6e%vDT*$P%L0ucm&JY+jKs_BkmA0YWBe%T@BEw*Uwd{C=QdEOR^=@ZAC%WL1(gID z7bXx$aUSP!JWN9uZh!m6voqG1+mr<#5OR#hkw}P1qkj|E7k?GxKak4VU_zu~_rcyo z4?pDN*e1kFxI`-1Tt|!k<$h6dgAE|4sJLihHmInw80(vDS-J5$si)tyTp}2GbMob# zmP}Wjh-61mu&F_3MQ3k|My3Uj7&UNV=X5>_=WOhEFp|sdZ802Ja}b?ijsdFm@BxW5io8Zc4BZ6=ImSt@AjeB zjiqb7nGdQL2rR3Zt*U_O3^TS%%|7P<(Qo9Gp_nP?u*Z=|uTyrrDi$bsyM4JWBel~r zI~{iV7*KF}O4~9%^LV|bh4JxQ8tb^~YD)iHpLA6Z+6yZ)|F3BL)WFYPU&Sbq8ZW*- zp=%MsYW(tr`>}u&6%q<+uRV_Xkw}H^!>EAg_m?Mgqf5p2DQqN|j&qzhKq9OwNYSDt z7pvWQkB3?Dz-^fzxBkt-O;Twt>q6WjKYGxR!mDY=Hgx`u4Gb+3OlTo~e&t5a`mSS* z|D)?FpsL!swIWD2NOyM%(jeW^(jeU^-5?6m-KC@ohdOkJba!{dq2bW*HuwJjz25uY z8-u~vhcVb^uf1l^Z+?p;b~3pP$*p{q8L7I*Jlk=q`P$Pb67%y-EBpa&y_#U0+w8b< zoW8Clc4uYEaLl6R=E0&s=nIByy6@zaFvS2Q2mgTZN^PcM*)z~+6sEHT{N*GlFNEH2 zvtOHl%e6rm4HG#2(>UG0?KW5jk-byu6AVIjbo0%iZXyTIC?qqmpy4hN*9zl;v4QC` zCL68lbfeDNE2MYo;5}?4b-be`U!Gr0<@mTa5Z+!* z+fO2ycG)*EzM z@s*)3GZw|XxdJzhTvxT!0cRLrgncD;#vd#f_{k0ZCo8`>{Sh)ET&jEF6bMcd z9$%c!bFqX6hfkRZ9<7*(S$}~1LbP$S_Bf`p#L?<+32OTU?_YmNV0m|>3zt`3?zSXs z9`lDvu%W#o}Mbp zjelFSb}f~W*?Fz%HO{13wE)6OZWjG7SV?pei#}SU8KvIgtKdbfQwdBYNX&p({LdiA zG3tr1Yu$D9#?McSLiIL*wvdOFV7QZQD)gQdE{k#GJ<03n`kS-Z;o)J^U@x`cWS%>w zKKz?ThPVn29>(^*ckaqw%T3=H$JfX~$l?w=!%Z37cB$KZblN#JV!t&AMS*?`t?0m0 z$>%SasUL?2;Np)LYR~7^$9F~6&lEwqdOPLWZ3LVCq@^L$(RZ-rjIT?0y$GE<-b|GB zPl9xMi)KQCeqHid{URN4-;Nfebi@olb3%qU|z#zTF_c=x` zo9-fVvC$I&rJQ2vp@uv~4BBudqEmTRv+A?3@a3eFe9qUtsBIjHSmaD?@K&?rN|&x3 zpXiW?WDYH=9Rpu;E<(*E`x@Q?^RVgS+a?^q&{kP0uQLS_W;26GQy1qD&ljp;cU4h3 zcpi)tA0S4$c&RP{Z2@lV_>sHf;zW)rlax$*vZJ;}=T>DAnCSyk(q{awe17}M%W!bBW)1771a8y%fzaD7Z9ooi_$+>Z7ypxZ3hx7aBN4iHJ6Xe$ z#w1Ffm!~k(Php~V5Bj@7!Q8Bh_iP2`rxr>5DK{Br;izV703E%YNuG1tGTBs*Zroy- z`EzqEBB3AEdNb4m&nfbcvfC5l&)7{93qOp;kpe(%_$?onIXYpsBxSufY{!yFpOWG{ z*XU%A_tIoUWj+KZosGAeJeD0=v=GM&)#U9h-6M*CzSmDh3DWid0Kuv0FiM=+sC@5b zJITGE2a4w55$t^kpS4Sk#Q1U>ZXSU)W|y{+U06Xwn``94?Cs=UD?=fj)6+}x1h#V> zbNrv~B(DZ~r)O1)8==+&=Vx&zKnAj>FYkM^aQ$jKIce^1G*C3b~Sf0V_Ng%~4TA3mW~*?3m>mY1Ej+kwsd8A0_f7E-yJy$Nv# zd#(lM2Nj6n5#DFV56(DNV7o+GWl_;l0b(#)qr7rVwp*SnK~j{ zsi7a2JW)i+jECrRy0I9s?vf-fFJ6(@)c2ZClS=dIb$l?kw^^F}irVb@7SR@)2jmMZ{2~ug+4n zQQ*z#aTnzG6wm(?B?9hK1(+RAlnKqH+tBr?ruEG1}PT43CTPcNAknoPR~)GI}j z{N#uNBrje7MTd^@^Eli60f42#r~x2;{M;eH@fz&d(}phv=QVf=cD4pHrofS9*kqLp zF{P!{G(Lr4Db)qaSyebW*XO%C?@Zpk(|A=>Qp9Mkkj1#sOG|K($>%lsL(KK=I;3l@ zg=MbFW5a~U+%^?ntv@~kdR5S4{*>xdGDl_=VR}FU86I=|6s^KI&2qrX0AdMsA=@)a zIstB>Eo}5G+Ib$F0)7|O$UsnNJ!U;HOVjsr!%YiiR%NM>t(m-f!Bf8c=hnbY>xpQl zZE%!*ax|l*fvsNAbP0>0)dz^AOVs5O&df!#8_lL|#Ua?#G3lcD*k4K0cE0!&e~gYb%l#F>l0a9o@xi_wjjs%%#W4Ey8!+>x z=p*B5pT6UiVH7AsPK4;r_1b~Qm1^QAI;p}*Bt$MtvGNJJE2)TYTd#h@TMnCr_jwW_ zSejUiWaB^0>^yxs#_08F+t>+Xb;$Hya)T*f;xWdXUV7NMXK!suSk?oeVnY-5Suz)Anb9#)X%{v0IWjSn1PqKbWzf^C zMX#Oj7MZb_=tAH7I!wQ%rB;rbpkBOmU#^;qA&;wFEX|z7Z}DB*c38Tn7QZX<9F#qD zw_9ogF$3Kvf)9s*nug7{*7?imK{F;@k+InZg2BrY6i=lAxO&dUub&$_Ns&>JNo}as zmLx=VkHA~<3rqxwdGSm_^4@Qdi3PQ4S0q%?qV2;z3*u!lDL|xdTmD< zQY!5YL&B6#EQ8MEaG5Mirrej)9`2$z4`x(URq|#wka0U_y3e)Rq$H(i2{=}sw%LbA zG`J2~ZN6pRn-%`vd~*<-`gsj#l8scx)p%bfF)<#*2VBe7l*wC zpJarc)|64z83Tn_wsKayor4e?=Bc^-{Ac`Q>cHCnlQIpf|}0_?h}opOI@ zRv}_MqsD7b=SKZ}rL3I_Yl!$;%Re(=Q8^gD`^s6l3a|I&&FOaYm(Q7^v_nE7I0_jO z-R9q?@pN}a0_S8&_!?H}ZSD9eXW@7>g2cyFMlg((j=E~Tt!728|YR@zeVJQqmqW+c>IC%M9br&Cg^=dS>Mu-!gosOg2*=C8{j4nPTN! ziIAP$26%vSV3cQ~CqcTqW??TBH%QD(QG-n!FRRw8^Y}@E=GnKakWut7^+8%C2b^vP zf>++NNwXLvQ?CI;o9RJONy942pn-)e$YSGVr0`}g{ro{Xw!2oa7|*(w*|TSX5RcR5 zsX2CM`>Co*gD#O9p~0~)Cz=%2a8R_usasGSsox2~#_hK^NYW9|J!qm5NrhcxBg&1Z z(N_n*dgVi*)HV%Nw<-s04_D`*}rOWb#*4i%ADKhmv zfR@PF8ZLhVfF#F454Pr4!k=3!XApDt(K76lvR>S0Td42PSL!Zio-_$wc*h>^Kf6GG zIWqyNCl_kRLG=5c;`fO7Mu3NHZF)ZxIk|T^Rq5q$_w`FO%NrPx`*kjltAr`gUA`VY z)LqoyD1W*w%P(Pi`faWIake+mDcG6jWB3&9QmWJXOngt1#TiT3d&$=VJwVHm-ss`J z+CT(fw=|ek7L3w`V)WQ0&C?F6O67uPsc^;J zEOK@C@_S$2J*J8S$mmm05$w9Y-t^wkf-SCu>|Es%QW!YYlPf&KU4k~FFsEnAt8V8F zbE#K+t1HHnH8LOtw~NX{_q4O7`sQ&v#|+^tD-tbzk5itHdn==P@-Rbt?4J%NbE0q~ zd)JRYo7J9#*p4J-jVDX%qLayTGdBbEm&xfM%%0(!pdDd<9|eW*mbs-zAjclg7G)m* zF{K39PtHw(Dh}?oDJ~1$dWU`Quu6MPz{yTG8eWjGtM64NTOu{WUXutiN4TFM zsx@BM%=GAN{Wfx9O7nELOj~x2cNd94MNY2zfWE`tvWUppdLj#}%qUVX^wl;IswtC9 zOE4n&YX?_^GuiDnZ3@>rd`u@UwIdsr!TRvOtY> ztPPeIJaEyQ1F73IO(lc?>h3eM!AaWUFFqF<_EIwFvQPPkD=d%w1c@Bob;{zQ46 z0+$qRt;dixctI?q&?~e=V#PJs>xU}M26T>puZYWH;Dv%-3V`8jjM&5D;go`?ln8~; zJ4EuzyTfHdujtIx=I(EA`zURQn7&vV+1eWQtwKCsT6JRZYCjdOh*|V{?OFe%i%@F$ zZM$wP!NsW8HMEM@uSK4R*km@(+C6#klOiTc%>bWU6?f3p`Q8*bw7c6WvT(aqbEPUF zJW{Ko@v-ZDUmv$Igewn+$wAR6+^>nNCEHR6%Sysejwv$u;@@+WcF_^V5rjfYI#oO5 z=f&3ayiDSnH^KX?)k~@Gs?w>@1Wi%!olEqVYEroE7Nr1M+m}pzK-3s*OG_pw<<Q=@6hfnx5T z1*(1^l^XAN*l+PCK@-hi40`m+!6y27EIJjxX5lu_%e^iPm~x+2y+>>9omm>p2zh?ky%p*H zL0F9m-PneZYwt+k992Nvnhjw@^I^z=P(~p}iIGv4k^0g^=UdTkaKP`4(3nAJ&%Tu+Si(PY&o- zPEAR6Fuu%nnTxdk(2{d<4^I|W06qjE3F^tdSzH;~pQhX+C8DNFWR9uneuYSnL2ukU zoqL~*h^6zB*}~tWJAMXmv+zFW;zRh|>y&W)Psz%%Gl=-Jzj$|>ViqB)n1)@u!!dSTQJr?{~>>|uxl zkOW$dwryfhyM&*Wl?E_E=%nf4f&!a6IGHK^!oSg|k~1N^8q?0mGn3SPD?N!pue!y^ z;I^k9+iWcvB7_GL^d5+#3iFNbvxpV^X|5>$78!A!8Rp9{(LObjjWqzojKGVFHCEsM z0s9f*d=72v%E0M^}SUqP)G?LTuF5Vfa^XKH$81TSpu>`eu$OCY3E+p~2DSHdLbFu90mz0FntJtNkQSq}I+Sqv0JgsOcmYYKM`sY?5*ODZQ z4YY3zJP#3H@d&8`vk!e76tu2ivm#fOV4*daHKxI4osBpbv|iL+?mfa@2k9CP3w4zs zmsj1+(z}zg{GDT4#1BvU6cnW?zC=YStK=2lBv*IZOdPTAd@zfJW#k<~c{|kIh}@+n z)1vgGj?;OQN@Qs2zoW~4%>O0%iwLjQVf8EBUADVzbCKM?SE5_jikQul%6cv-VrQQE4BX>b|uoVdiJo z7nO87E)@v7Zwun0-E4zg=AdiNo;o$sV-Z|7XXmH zuLQYyii@4(BF~Lz4e`!@IXzW-;73C6j3ZRLkCv^I$UJHh7_U=8LPO)IZ>Zwl8hwA8 zg7ndLjk={O@~(vb@I1d{npLL=;e`$czs<(U()y&j;FfWl&p=I=5U2Vy#)h!W_X7s}iy2|fLGm8(9+ zqY6zd#?s67mpBli4c=6UTkFG)b{jlHS*1nV8{Ux4Xp3<=#XNsbSh#5x{o)1ZU0+G8 zhT0ERNgFR<*774l)5G^e>7&JzM8Wf4Ihu(#r0z0JclJ%tS7E+wJ-E{Z1VYxi+5^L* z6CSb-@x`PG1!T;_hN=jF_k|}E7m_Yq`d;-(M zs0n(ft7B%6<=mJ1&&SKfMuHR{xhZAma-8Obc)SR&@C_;`Ea_mMPg^#}0A=sp3H|zu zZL`XsE2@Q>ieO!~5qJqBacW1CuV^J*S@&!`?==^gNS*Z~GECt-OO1J_(|LS?c(Nlx zLSh!YpuK6>bn*{k;zINTjYT`PonwStKPJ*MRBF_0w4|V|2CeK@Cxt0>^sg9-4wfTG zq4YZ;^oKv~@DCl7+&g9$z!yT-v)qVLB0OzHa*xwA0I0GE5jWZKBgg&X4cShanVGXw z$He*Gz75PkPq$F(z(H;|&zl)Rg4!G#^sAMwtcs_1kt70e7kOwI=?_6`#A!?Yz_{`c zf;D^@^96a1p4MsA)*tIOC5=|8#o0{rb~B!hMYP!sJjU5gB^15S58^I;q$=cIDYPCk z!(LEud320zrK{4&>$v3Hx-C7tQ3CpBj}UhNRCc(Vmqk&eP=%}9#nefd9x@2jWqnCG zM#QTM5p4_y(#;aWZyGS2GTzP29A@-%(IDnZKH=wd-Vk>xu=$%R;ZJ)bO8y!;&+A-D z{Dx}}`aRfLP~CWvB>ueItPdePY%KQ4!xKBp`HO?a>tF)#SzCKsQ80opl837c$w+zSyATM@d0kT)vN;A>sBi<(!l_*I$smBBzmy zAC@ZV{5m&wLQ24)_ceJ-tJi2GThb*1RUIEgx$kLnMWpP|l`~RnA_CiB^ZjjLy0DK< zRbgJ@D-Fu?Y!!On4PG9P6dQ?-7FPfV&;60V4p4Kp=}&E7S9&;G zyVwBok87P-VA2c<>%aH?vGp!=mtxXb8Qx6HBJKAeS=DfqDk_lw8QB&~k(?q-Yo4iX@69XvW;l}$EMh=f| zFtM!#mDBzGrdp<+&;IR(ffTcMNsfIKz*riIx3(n8xwy{!+4SDtd&_WLr!qe4n}^&?2U z43sD5D(o574BfTKJ~}-$Iqy$A(_1?Lz%~0pDva5VOABlx#)QQ#PK|R>$F4Z`UNegZ z!3(G;bA~=bJs6V*Dhmc=l)df#IM}*Ibb;L-gTFYk8^D4x?TvT_9Rs<~_0k;u5gght z+kF*MThH%?zjS51ct(fmYVx)qg&0d;zj?8V_Kls?0V3LftJmo_9$~-H#EWJ!F#Hg)51X3BOsKa@Z-dwGs3lY_0TnJ2n3>2%LpMd+8)CNK#@k zl#Z*Q1P)ufBeW|M2<+)@>@z^0I^_wd`7Xm(W}Pyb@Qn)|2O(b7x}4;ZxaE&2az#qrElJo3W1)PJVydh+lmW> z4uiXck=)@C>ksy;x&VT?J8(fy=Lov|I)zy{h>`wHWrN;n zC!K2X0*Jd4%Hx;_oXrruhFD=e@~Ly0@1D8*8PIP^k$loQbr~I+)G>UaM_`h6{Vi}M zkUX-LTF)fh4(er-LckAuhQGZtOow@#Z`^KU6}}I`?)>lT{pOc8B#lCv zg!+plEXA}i!>?KC8l-j?zW15wZ?GwkS5h9?QzXcRFg;f!aXVjQyjm|KGJ*ejm@K8| z;|7@k*U#@`nBjLV&#{DGBr;$3;KbNkW!KWmE10!&_!UI*_5o=8SV@3D#FR5| z*9Y=!!WPP-cTGE;ojs#^c8{}%CmrL;>ArE#n`IpohX-5rNDh_iGRg{1V`J#`?`{@Y zN*Zn(?pduI(8H%JfZhuFeAf03{?b^)vaYKX)k_g>$kW<~CW?F+n-Dj2z>4SiZoQ*1 z&;|;%HQx8lQE>zyW4u8YVkxns0lyeddW8W??4WJeXO>;>bCJt|QHPuuQ{M1Fnep<% z5^Ez5Myc9Tu~K=v4b(ZkK$$~tdFdPb#z=1bXG8%3IhgDz4-3q9EHA8zJJFzUKi#x4 zkrrJP-C2Oi%;UGO8s@4tnoalJ`qvJsd~Vn9l}p~cJtiGiQ>>>sj&mg}6&>2tjpMW1 z)>%{naYMpE9G&SAEbAS-4`&kb%KM&eck3ZtWE_ey03SwAW~0|RkD%pR(>t;YO{q#4 z6AgD3-dG(WTJ*%?;-&Fo#G7L)&>Ww|dS zy38(nlbz;By5Gcl>v?EV3CbQO3$_dh@o_9eKh%B_>S1CNa@hAX?|)@OaySP}x;9N1 z*mNb}hDQMW0&IRgxDLKr^lk1uTroXwFiHwvtcRGr2L?TdJE!G%gCbG%3I1e(8qWJ8ddTw6LgIRQ zBNMf8veEZgXb>(o3)?&ym>Lsg4TQf$3utf_?h+I*5WYX-LM8jwbnK|qLkv@fH`F(% zOxx4+gG>%GV|lE0hzRhFQK1^R>mp4Q(cSO3_eArtnEm*(A?peQesN#KTki%jQr_f$ zbc;2L{uh|lDjZb55pMw`bVpZX$QVM*Fe;eJMLMkYA{opD_j)wGyO-~JRg^CMS5!|r zUpW6-p-?uzAc0A75qS^P!8L}C7wjJb0%6+q@V)b-F*sbd2K8r`!R8UWz+~TybJB*@ zU0GRK-Ccolh9-8NO=!+YPGiI6r8}P|B-x%QJWUAKdso=|@=N4!m`QsAxG0p7u%aNc zYyJms#Z~@V8g!)iiqe2DlbGsjW?qMMz8klwHz4o}Z%t{$+KuoxM>zX6(mGT2b z1>-X@KMC^9DY;BgE#AIm3C2e+E)`3VlQ;oV54$Ho=AHsl= z^S-}oUjTOA2sXk3_m#V|mLNgN7usg&iNNnvZ%f`ZHGI-Sl|Q}U$+=*4yNT5v$~u@F z@?NBR5}c6yy}@D^hwpC6dcU;%QZXWLcNtT){JqmLx>D-+a-)tm7UGxNsuMPb0@`ml zS{M7n(b3Ki_HlV`2)ROvy#nW@I9T19Fu(w~7Fh76ZzH*n-#f_)g*1pEMO3sAHdNT< zHE_DM657y%<|=C^{hH0oy+RMQ9~Tg!*yeZ1oP(N^Gymj${GFoa@j8H5`UzRA{QR&w z);p7N!=iM9JGWK%t(qPzJQ4;Vq>B04W<`XvSrZ9vrH)ntSVv0ggQ={svRlk0Fgo!3 zW+>Q^K!l{v_bg@QjlKjS^zY!}7bUS7Dm~;?qqs%M?>DqKF$&_Xu?c;oH?oq10Vjp| zTAUHnWzc!`Se4X|O_Fbba7{#`0xQB4Uc#fC>7{I^d^h{?B05BXNvoLpQeIw_NWh9@ z&sqcpKaGLydWJ&Qgsva7yFkG81J@L2ZYI)IA3U?UB{emQRL(5<{7_Mdxr?gdl7)0w$Thm`pXU^KNKfJs85E2!N{qW|TbAOUm z^(JJCCfC&JSgrS8w32^$(*InLZ($)I3={zTlJTD|Vb2FI^v&WMrIbppbyq3bCaQet+IDTGyGfM#-2w^!UVLpK1goAtG= zH+`v0k|&ag!s20${5T1l`m5+y^&P(wb+YR(Ctp<6)%9S>Z28juuM;Q!Mz$<71ORzQ z0xv|9@%6iC2zV-`e9n%7?dBtay*eF6nJijTE>hT2pQSmRM$pERCfmJX-bX0+1imY z{U2}nH~Oa|;iuk4tR5!F$LNR&Ew^wRm!lmYjOT=BME0MB2*04ftv^d_b0MV9**7}W z8pL|+)B3~CQ~Eo!{#RMM(O_;-d(n1_xWI_Ny7UsAba}d4Jq&wBvbN;ae_0_i6I15t zR3`K`2Fo1V5QX?T%9!&8ZUCrTcQ^JxgUgnrC|eixU6ACeMHTp?iX8y{lc(Qbs5) zlY6D@3n`cx#pRO}wGST#koeB_QTS>hZ)|56PAAlKBtC zGwAk!xqvR8^^svc#&5uYgVgQ0Y>UWD%AB?x2@>RK)NstPY;|VO$n9aE+!f5;q z$!cyce3$$u`BgL`?CbFheyQd`*iz;{4`FU$2%!9ojC@Z|9i4_i{j005!>4||dzEbC zC1Qv(LpAyt6O#o@;AeV8|g9ayhUt zdV4lDdNNPAQ(Q03&jU)5E%AtpC-I8?C5K=c4kd#xMt=&6A^POMzwl9E5C^1R3SGpH z-yUm~-;nvm9?Y7D;7H^`#<9(MiIx~9EE@Gr&O1!`fq(NC&?K<;=1lM?RC3rU>d zHKeJ$xRX-dmqqLnSM`|GE?*B#%QNbAMwFz4Z#Jy@`-}c{g?|hK4c?Y5@yx+d$fOnU z^@_T0z4pC;-^*ye|6F0`E=JpM62ZBWuH`;ae#PqXYsrE2uV?<_R`?MxDeAo%9mO|W zS$WX=C7HgHjo1S@`NdDFKYV8jO?&s2^4W;9=ttVJN8GRUuwf90KRyY7h>MzF!*-VY zzib_;bt){X*;KW1zcf4$qe>^6+~i%PMi%x-Sl5UwsO>4ceb!b<<^Kc*f&72}Vl?uL zE*9KC=^+zQ2{j)`m=(E|OLI1$QdAbCBhlrR-$U**TZJo$JHa+!^uX0fruf$_*ll6! zi1zY!Qo3@XY|U}k!T0%W1cxz>%+zak|sDk)d@Q9bGC`atD55_^P}VduAf{@3d- z6;Z$&%48dR>8LO06=1Vid;hJuUc_{2{>BE?tR(t)t5K)ZrV=s=CtuOC^?LZ zg&sBXrW3%l%aLcu$gGV;_4XFBCPE|TXyUL!5;po8ULB8yC6uAHTap2UJHb)^;b+(f4hyk{&a*!LetG<3VAr z`=lVEWQbm52pJM9R)9FhvSIL_Vw5UcS1)h<0EO4~xx>pXtdgasiWT{x_d@?lgTN08 zr_MrPBZ8sF_J2wcpheLzQ24!Ak1m<}OIg)A#~i+2EI92(LpKS)PDUSCxxwq4C)I7zu%L3+#uo(DpFtFua>vmf}F{{S^Wk=b@mPjn>(q-rw zw~GutwJNt;DswH=l|kg*6tU~{c@x*9#6MN=?}xx21C|2Wk21C0Sgl6@6U-8AyFj(q8aCX1Q8a{TSj zV_2~Cq#fydi?k8Z=On*vxwNkT5LjA!{^Rs{eXhsV*yz!8;OJ4eNUqNvt?Y#`MZqjxZ5^12R%K6En^&6(BQ7-ayGsOT1 z^zI>_Ir*hit|8i1)L$=vJsj?mSRmYC@QKpEeW^Y`;1!lX6kEQgG`jiifff)+joHcK zq)82;JfC)REALyeAApP}R`ymarx1$EGQ_`L zLQ5;+kq30S0nKaQ_Qg++E3VO_OYza8?Pu3BPJy}gV_1X8@;jp*sxDACRiDi(PWzGf zSWFB;5b^S7fS7v0e9L+`_BFU5^}5Jlk}`ULxqgCW|2<(^Xep-DcZWpIlo}gZb~j#) z=D5yHHa|CbgyKuMGibwho5GiT$M>_zN)JnI!W!X|e@*Hd+yyzkH>1-+BJh=%`BaAJZrN zH7Te*GM_TbAJ+t1#0HbJ7uI$_v)n2~1C4CK#J%jIit5Qdo={ccQ93z2`SkNfI{xCT zo787WAg#$WSgA5mewvm2G@5&`08Il(lbR-Wq`F0Qt5FV%&9BiEDOCEn!^!FoJ6Vhr zty!5NVnb_e>r0Fwx?Botu8_%0u@I=?Rw_5+{F{A633`%c0x#}jd12*unR!{RRr_-W zmo9_iJnBx3u+m!lCVzkQor}d_`dWLe&XOf4!5Sj3-$Z@DGWmv9dcwGpve3A~X@oLX?WixAL>R_V01a z#0h_~W{M~>a(~i4A9czF*a>L-ZY5aW5Rl$tuOR@N`4jFn!M@Zv?uYll2Ozknq(D`^ zm)A77W7wIl5a%T9j7-4mz8%t|Q8Rqt33-9pNs2+u^l!)emmems@-KX+S*@0u>GPWK z41FtNHrF}$?zn-D3fgtrMi7@b|9XavPotMRS)bdaO5y|=?WP9u*9QN`g{&jx*74{0 z^hsGwlDm#IlO@rjnz-4{Fc8@IFcfFeSPVsnstv`;`HWQGUaC?1eSATHg#C-O)-9c@ z;5GE=y_bU z(7#mnuXX$xoGinG)3W?@3R8ucQ3?C)4XZ~At@Hi3hQ3E6R9^kx_aj?FPyjfSK42BoV zoozT&p62nv*#jUeE+VgpU?b~9%X9Rr=1-r^xOXXzj*T-=*y%P|E~03E*taXL?Q#@6 z{GNpk|NpuVQF5)8k24GBE~5>%OQVk-QXdwl7C?g%~&Op2*0zuSaN-|p5qc$I7PwtsE3{KP}n^1i3e^1VVR z9x2rZT^1`YU3z{Nt|8^s1h$0yyC|%utk0fe!pyYq6+A{Mb!6$NFwz?2KOBNVji-g> z`+k1(J&B}u@Az{KHOZLdlNM+@z*~FHknfr3@Z$e`guk7l=(7JGVe(6vKIFcwEo|VfrIx35cPH zwsnYu4(#Q5Y=Fz9b=9nWp|XI~YpZ53xII1YrDPC-x-*Czb3Zy*2K^fKlU}BmUqBj+ zI~e$8fR_)RLj7aM9z|^gbC|8Dz9P1JmxwK??&dH~U0Sv6I9ff+Et9zpBJ~($7(Ndp z&Tv|x|II-BD+VV1C|VAZ)Zr}}F@nZj!(Y;w4uO?rw<7s_s2e|8cwqPDsu!9?325F( zcFFGCcEl=AK*XcXvH!6wBTKjt3XH5oWH z+U}Y)jdk1D4{fMyRX$t?EPHZb}HMDt?Lg}WE9yM<-gHKhR;_ZA#UGRM;s zS}4L25hX;sb5QZNBf7`IH;uXGlC!7q`({LGjBgyD-#;GX@9i@}L44FglbaVa;MJv3 z+li6;yP67+F5M4TMROZGhETbY^chb3oe)kXCi5gxuzIM)K+@Zt8jjpwd6fT9NGfIW zk#gx-9?%2^^mMdbj_I8ZLcLFWr*PIq=+;17c~Ux~*{s}X4GmjN+Yc`4*d&n?)}^oz zR{h2F_C-u@p1R0X#2AJv0LC%RIz0K=DNkQScDs#%FaC!V4$%JB;C)5R#TFVp`qgZ@ zp^+6E$s#}#H_DdDglu+iQ4+&Y;u9tj77D*V4Z;8C1N^;NPXcln0HsK%8X&6pn95_; zs9N~l>Q%kZo#&&`u=;e`rpj&?8*kkKiT&KQOLmAS-_sx&E8?5|DW@#Q<0molKW>bF z3bSMSy3Tb%Zm&**u+4x0#AYdJd&fLg3z8aLu-Y<_qzl^|bfK`Fx*o}1%XQx*9uQ0j z_Yir~SqzBbipwFQDSF9G>kK(NJx=3i;~M~P0cZp-NX5PotTPKu*fdnU@;klFo8-}iF>o`RhEmYG4Aqk+s zlX0!+ORR6EBRXu5^i1Wiv_gwng#(-Rl+WqMk*v6TcMrv2|7QMv+pEWSZBz;exjBin zOKTK4u>ntM+JQ8fO3uftYt2h&sIi!sqE|hTE3B)YgU_RGS<{8QGJo|IT3&mWI$+%V zZsh}1*rH_%atq4D0QGXBfJ|0uqI!J>w3I4jb8s1~-SG3RND_-Hh%kXwZ`UA`C7nkt z`?F-u;umCzWur&+3ZGmqktg>$ir|BR5vPrw9;3E7tWl|2IyI54g38bn#+JuLCgn}d z115fR$Jx1iFyh(2@|3?-i=3SrF!5*HymE7$m4t%^3@n9}43LQ-*_&%rAd`eD$+piN z_r7CsEPo^Sf_cIS`kEoLQS{NyHz1)}sPTEp*pt9Z{`R5*V(69`jd>^KZ#K_$P`x55 ziVaynI;iz_1IVLe(LQ3DY)m?-bdpY6GCLeyR(?f6rFeT=rB_&Ng&2qcm<6cOOiKeE zOqg1nKTs4Jed6Q@`&?GES>a$-pQ+IPG8=N;mqk4h6Yps7_UDjaE%Ws%sw%rxsOHJn zln${`i|XHG@wZh1wv9@HJWiqRa7=fqd0E3^?2YK&?#5`7Rb1|D+yP_JMvuEj$n$3v zAE39As)AF<7P>2O4ZYT(S>e%M16IF_d&>xR>5$F>YP~)Uq$e)bF=V;oFBT0JTP=K0yy8qwN+uyI}A_t1b_0U+^5v zlHMrCRHZ#O)0gM8$HU?sdr~~fXrYB8JJN7Ph%@X6B?hH}S|RU1=@}xvu`i^1h|C!E z(Edtw9s@LX_5f$MYUll*F+8A83r$uTTBy1rx|JomOhOU+lmreUF>POP6tZY(kXb%8 zPWx1qYla}vDkM6l52-&JGiQMneEJxP&;|TA5(%a;a!A_O22ONnKA{9Hmnm_EgiC~( zaNevXb@wBSFqXx>53cm%k@|Z<|GF|_2Et4JJg|8^Pu|^Y3`)x}f7h-=kl2Rph@-2m zUK7q>Dock>$3W^Rw0#CnEnl{x)Sdaw`-tDAfjtN=mc(wf)9i#z9w&+jHwgOWdXi|KWp?;f$`A_Rejby6I zuw!K(54B4>`#cdbT0BuYS55&L1kF{td^2^_9*M2N8BAyBI0Zh|cFBYUm4`q^HLW=MK%eD+8L2?Ck3-8(@u#vt zFmF%Lc9Y}Ve>}o(n-nlY6TN#7J2*=++N6@UG)Y@C$6FjT>B1%xtaQQc3OljXRu;Xk zSQJl*N`#}mVT)>kH;_#ASp90^X;*}+898@qo%l^**;C;lG!w;j8KX@uaTN|T%de;R z3ES+ak~HgWh^RBV-IGc{2pvpFd5%y)hLq|zBFI)xye0)n2ID@4s6B=wsVOx)ut5@l zDTyvUy!Z-Rej(ou11lBu80Ygmtk0Dn>sHHU*UB^5eu-yJX9-JMU^NRfqy(IRsUCtw z$p4q7__rWnl_oOPyG>b*%@fKDJ607URjFb@dVO0b}sg`YrKUfiD+$~@vWIIWMn+V^O$H?<3%tQ(md|76Rw8O?2bq***;p~r ziHSM?OeP|OL}{r)pqfC!{4L9n$EI19zdXx^|7>Hdc-9lJa)DeSIFje5ed?&jY~5Cv zGKTyUc*<)V3D<2uG~;rC0#Xj8DEZBIcJxbf*m8J6I>zWs?0_y1e&Q`pW(AP>;sceU^1*|Jmg zEQyO$+^dX*dhYyih*4m)`Bn?Gqcb)8GmD?vp;{q_{C zZ&1OMadDNIDkcPdY}D{VHP&s`2%Nr7$uj}Q%ur?)bm4SQCysxrg1kYXyBa+C{f$vR zRc`SDI^{UavLh%7VIT6ec|;6X67c(_$f@g8hM=39$xjHS%*fF%$S;TJ?}8( zXUvrADj?LPYbHM~mt(X*8Pe_2{(mb4;bH;K%2Cc!Q)X$`i;$m|Zrc~P`#M&|fO`N! zO_+q}=OpiNfv{OueCCBc0?aH|u4o{dhsGLBY!X?~5W+uQ14e+lTaqv93{A%Ms%00H zrSU0*g{XoMYA(xN1#NouQy~0BSFX`DH>&Ya+-qb*n{ykRnF1M+oOKPwXh%We==O5J z*Zl9?haQfzCzreAwz{b1hY`Lr!oq^$RINn?_@g@yPu*TPm* zvPLVK6}AXahGH)Q0yFf&If}t0=W>o-6;&fd2gq|G5gv5~WRvKInYDGi{8!Td|Zs@X2A!yiH$JR~+lytKyaX zp-1qVaZlQtZwb5RRxbRgQkPHnW!3UTZyI(Hv3l6H7l30aertQ+V*>_WX=hQtfX&a| z%_o?wWpW5VLzh?9O+P2sYcxQTo)N2ru;8h!&()aD*2wM@lpx1(7sUtBIcQx&U5=g* zdC~%?KL!>2kuDel%l#u=7%uS_;@+=0Oe%*KYVEeG{SRf|9oAH~y{#y=48o{@f`|n~ zIx0o!iX8z53@!8`B?OQXq=cq`9Yg`?p!5)GiV#8-5ReWDBovWONFo9W5CY%9nYlCf zyT6%x=MSFe&~nb%d#$zCdf#`ijfCWSk{_7)w4)4t=LXj%rP>cNLCv@S{3L&lH`{k! ziveJ)+!Ol*JFqcuB>6+AIY59;XP|d zzTEv2h4A2)?J$3d!S2(Rc-M#9u;4nn&xv_i^O^hQK8&7ia6kQRY9|jM&veK8EqOl- ztUE7UOZd@`^`D5g>PzG2JACg)PR7&iXE_68`WHY0JNj}&hb5D%1My->c(E+r z8{*BMs+2ZhSs=5Quvi~JXWbqu|_&=RXxa&$u|hx_$Cs z3Ucz<*ZxMKT4KDf#UvDJd%XdeTiaGejvLTG%m4g9_>aUQtbsq{GIMNSnFiOxGhMwy zXP_Qb$>K-$x z>D~7r*k~e^f_2?vZ!pSt%~Z_XI4|s3eo+8?W5UHSqrZGnDT5Y;UX(&=-meNt2Q z{VC|!Lyq_NO9C0UVh~E+$#tc&jcY)Ok}bV*w8S#DT_ko^HZ&D+(K{uwSjkhvH|LN! z_2OXl9j)C1ZHe9QPDb#&fLRnB3;X4?b_7u8>ik~ke%b5Xdop#+m{LI1lE-f{O>X+; zd`uEa`POREcGh~OY%9cPmIOcB3d(<(%Gn#$Dj5}Rr&$X19xNIc=i{w z6lc8=D5m*#2;@_#)PSW>EgijYVC}#?KbreZUomz{;v~=?$Rt2^+!S_juHWBN_H!T?mCA=ImU8*GB2j4B1{jWVMk~ ziyNKOK#Ez{a6n7qFW+;|@sj9JWEKuDM|o7S>q6mEEB!lo=(Ijia6VqbIuzAGUzz%s zMye>H&)$@tuGmKw=;~k!b#)+ zQg6l}B1$ZYEcQCNhIrc-Ehe}6T4Hw{6gV!6=&|oKv{?4b1lS;BGC6E?AMuJ!-yXhC z$EPk zU|_UTh9wH&sKn3O6>!S*4`G7M{9XqLde(hF7HI3dhFMnXf$^8fK7z>`(1+;en47-Y zYb%fJPdov~yRMk)kjz(AN2RO{&`yhzazQW@KCEM-Q1K%e{7qh8bjQwJD-_Zt53)O#_)qk4r(X>$HClYZk z{J3#Mak+bx$qR#rWUJ#2$@`(`r*Irw?W(6D@{`G-*Hur(#Yed>Rm~0hlYa`RjwrX( zvidHy$7T1u=YQnt&qcOt1r0loQ7x^uL39R&g=(4gB&JtZWHHpwC1U={r~tIyn4@aY zKwNV})j^9Jg zgu96TWQTy@xc!(|cvjxqZ;y?}wf=CFQUbiv0C*W#&L2++NG|7*9yBjJT)!8%b z>&vd5$rBWnd_L#x9fyR|qKZLF{$$LJ^OvlH&;l+}1!6}#g=g=kXaSR@Ftsx;Mq|qT zqM-WF&R80%Y+<+Grzt!==3|=N-m6z`33euklSbsSK?yxopFHulDZGC@!|%;%3)n8T zAM3@5g#oxxbS0Pt3MUIG3=W@}m4ngG!T0^T)zCAP2zxejx^N%m-Jg>G;+InWi_StO5#TD%PNeiir5g^3|G|4UTE} zACLAQSJy4HA08(j4JchcKV3QO)FX+alTKQib2ccMts^~n{f&3)|L4MiLVFLb=VQLGap7bjGarI-$Pv_yYExI1_b?v?grF%^JrURtJMiH;86 zj(@y(Xzd9QfO`)Xkd}Mw$EdqRl$|G`R1_CBaQiPi27EEG&aSU~400Hy>w^26DWIsq zZy4@kPQw0j`D5lQs>bK^FaPq@AF)00^45bEZ`=GDJrdX!$78e|d9oWoc>#RLZg7#| zH2e^fr6AQSA5`<1J>WEykf^A0?zYFV+=ze8z<)+>{n~Kxh3~gWZR=OvtpE`E3Pjf< zrcuh3tyjtD$d~${o9yE;+ZWSzjP$H<;jYrq0oj)>j&)KzE>LaCWm)p0z#(o7CLA6S zf%Z)lF^MX*L&@E!jYz-ouaOQ5-Z=z%wB|ZCFxMFq%|L3hiXnGFh z(`UVr66Mf7LMPNnWZSMFg?5SNjahL}ReW2Fe1)xojm`XjR`KK=g zpDE}^H}l`BGMBywy+Gko@COTYG1scx?xAyml> zCk+eLW9LXkTyO$+$#R8J`lUcPBmQIB{&wnoT$ORojbKx|I7h2bWXzX$^1JULE%EUd zWvB{Mkld?!JM(H$j+VK_2_TAjc5NYSNzZxsE+_((DsDdDTXESOx$_3;WkAbJx#h@; zq1l5$o^uQ9B%pAb>4JYY{{3d)6YONs~hhyX6YxC9stojS@D6$-5Tr{%%)5QB(@zEt3NMX zwcq7u>Vt^tc_(l&>S{dD#yw4ZQOegUThqvu5xI8zNK2dO#TzM-ThY8WW*?B#7zXdx zG~Nl&RAn5MO=)Ni92IOfaQdAdoxeRv>{;<@B_Lc-<@K!Yest8b_tuhc%X`~ zV7vx^!kbv!QA$}@KrKkUL_v39aW zfL`vSc~IuB*wL3e+yKc@aFlXFL3=y);!eUYY`N`G(s~uL z2*!^UR?Hiw6}Ujau$KHhSjhV)@y=&*4Uvw}nbY(rw51X()g-4Mjfur_V`Q^LNSel~ z`bgJl?&wEJwhEb{` z_aHSFl|55#5yy?fv|@x^miI-PlkpHx^hR_%XV&g_b#EbVJ#ygPnt*_kZ|hwYF;ad-+z(%%XX@W|TjF@j>%t z)za%bNXE>m|Kr*IGKP%s7DETqK z1Mo~yo{c3%C49}K4@vRa@=5B$VY9}@8@9K1Xqs10!ZqY3-iL`Ib5c=RBE6nia38#% z;H&Nqu9huKb&A92)Kwq;mxSnAf;K?Ln$MCilgLRo>$!_z&Y4h;nad=4;%)1U@`ULj zkk8tD|0}*1#Cgi>d!sCccbTq;v@*d-FRS?SIb!e%`2{{;0VhGp^r zBAi2WN4@WY06%vb{uaIkp$#t1FUHbaZe*R2IzPfWk;v{gz{`(|eN6CpzZMnx?B8M9 ze|MP^2TL-r*1xE+#Ll%m5+j>qgzT~B?2Ujgz9DP|mOG*>jMjARCfy|=3mcx~Mv+aW zz^Cc@<`&d1s1jY4?SM$_kzvU!_n{C*Oly*q2~D`zmU&JW7Qkl4pA2@18<1feQ7v zIZzndDYN7CoSR=J^-9|@ln<=Gs9Z;|ir7k0M!S-VzG5`3XPTpNW}|sonz@mB$s0(-T_*SKD7eb;XO~V!s~Pd)2<-#pA_a2mUxPKq7Y( zwn&exO)SJ{!q^+9CD$Aw)t?C~pmQ8q#;ZKdqdk9#qW-9Ojv}^$zL|od z)T>iVX#lnjKx)Nh?{_`1u%Sc_dcIPjfqj>_t_hHdUB5tc#UO!bQVEk-Z3~lrE+YBZ zRU3czAz7%S!?+i#@C&-Ho@~C{E#-nAsV58c9h3NlX1~VDx)EG0Kq7ur`IiDy;VqYW zj%t7Zq?NfY*0qZqAozjVK(d;oIy~D|Jgf^F{O0?b2clSrs(X8TQ{r$>mv2>}Hc)KU zCxLNr{vuBNwW{e;tOLn`n$muq&P=yME%IH{$M=aai(4&z7|__3Nb|y|NC)i7UeiTC zUqC5pY|XkjOCCJFHk>-4cT}R;BKZC7ph4uaF0TG(UyT%*-)HYXvoOFnPw!OxW*^cl zSrS}7p_!0!6AJ$H63*iUIowjb&4nM!xf2V1h`ujuu5<&rZ*W2inyVUH346aWoc9Z> zBC|7CHsg?N2Pp#^SteV8iW9ZGN^{dzOX6{c+@VCEW%E#RnD^x7r@G=P3B~>}E(+pK z;%_l746*avEIJD>>pA>R{uSmyT#=Fwt)3)MgU|d7j zKHlTtq&T=XU*4%JCiKcaLGDQR7ajla(OL^xRg3kk3ZoBG1#Oe{egyk722OWH)cOZc zP=Yx|W`5KJj3ge8Ffzz;W*##0YA0oX{n)#tTUzytFTvucza3M7oib+*^>0HjpK}aI z*X_tMjGcGxm5LQ0b{N0%$%Lg6f$Ki(7kGU=+5N2u&NWtKFORBkrIm93(qOUPqj8}D zIoTyC7s%tA4|TiUz_h#wtfc~_o=iAFbH4dR%>Y>^m^^P z={pp-p;w^Nou{587dm_|6PoJLDNU9b*1b3K?A~4x1FX-DN~g^*D7561`O!slPKkh) zMHiWiIGE7lW)9gbiShmBHFyEa(Mh-5_e}iI2_KEh5Uz@?%^2IlEW&>N`O^l|j~&;ltKGQeIt)bg z^wnF@mSS6aHt|J4-3v_#mh$&Ld2N06?+MEPe`S-k*R=M`l$1$yZwY*~9OwEbzi2;? zrr8}e3eJ3`CEQ@}8#V&V$$%@MrQ%?fuv-Chm~%MhNwqb)MQ**ZEj~+Iha&U|eu?Jx z?Ph0laS;vN%e+kf1>_<)_<`pcrWO7Kx$oH1=a01n8Qz@Fzuq3;uN@4@CMY+xPzT%wPZ)%n>g0rNI3ME1cS> z)+{nYKd7-4Tvs);U~~G^o}VH@jolgUg$aW06}Mc2S-o+%jV2>95k~jE z<&54L5`6jB6ezF&|5U1d<|rI|0(H)z?jxax9N<2CC3;suVI|zdl){Zcg*zfezjow1 z%+^y>huy;HZZ`N*9f&)vi_lN^#u&Gsv*7D5xmyZyzAk&geGCS2gEV@m$aLFaUqWuE z3HM>U;8%7~1julLF?oOUSN44Rk>8dJfQ+Y`X-h*Wi=oSsD(G5YLYL!mJh2b z{Gh*>cBC%Q_?y)?*VjHyhUaE?r0BYTsr+1E3dyKcclK|nCkhn7JNFU4M{=XQFO!(+ zwdJ+jgUlZNs3Wvr)|TvX*c=rdl~sefW)+mZ8`WmAN7?RX`I++%tkNu2iu@*0G~e&} z=|w15X=bQG&)9-}#O1-vB_N3r2Q=0}m@sS~o?CP$! zDLZZMtY&!FoBu2-2}`v!rSQ5?yNU}^4-UL^y+Mh<`Z|X#KIQ@K6FZdMKY(C}d;f5X zrlc)e$-yZ%OU7+DbIetwvIGONX7N}A_7`!wFgzGPd8gSftJ=96M=!XcKAg}CZoKtf z(Z;f%Ztk2&K-gSH<4=Mm*io7l7)lC{B;>_$hCSq+BF35D<4)s#->(Dcv?JAHQi(Rm zh*I9Z)CXU6CqzT=o7%{dpTgdsj=7ng9Z^3n1r04O!_2avHA1NM=lkn&7FJdryWJ+ieAH0xGt~P4I6Sqv?w!MHjQ; zA6`?VfGk8;Ol5x4QH3=KKE|Tax2&uz*i|+jA|fKOw{ygfMc)h#u1+2;Y_~>1YAyjS zbI*u3HkLhDIC~B{_1PwQZ*sB{ioSYJpX`PFt77=1UEf#3N&_;w&9KKJqob#X`718%%f3oas!sGE6 z#;X!#L1PPx2?4)3VOKbUx~ys>RGF&g1oVttzaQukQ0ua}4qB4^W-23vLcz*_Gpo(; z!G!0X^X{0O`ppdU8+e~ih=)A{EfCM`dPI9=KHZM}xrW>o|2!rZ=J7$gc~xo+Ows1BVlRZauV1wb~{lyieEk_~&{X_qS>z!V`3(M5E1)L|1C8 zkDqx!B_%7jS}z)teiUUvT+mr7QwlT+@XFHG|OlY;<2DIJ`v0dN(%bv+-F$qz9zybQdxc~n!+&V zfm|<)ds^~`ciMd7ezzzf7nhJ4h+UtjZwjY;RvTH?^q*gln9#CfyROzxYn>t?R;9f* z(>D&tu&&E-mKwiTbOyDi{}d^3t9pt|os`hxjM}7WeHEoTvDPosKP*z@3g_k7z)F6A z%AwQK*Y9*_F)S*kr)y$#wb)lx*b-Wmx^f@B1cmUcpu6a~@|>!58iRK!(c_>%UiG*z zuF}(&UhgroAX_mz1+hHLZfQOi>#@;^o7_)h(dSqE5UdW(u?YfcAvbX8QoA||zt-Aj zF~g1&_FxL`ZeS5umn+-{!9oLciW@0+Nhp|&AJv6G0!xat&iVI#83g-K>kA_%5Bmy}160V_8!(B&w{W)RH{%eZLuIja!A93UuNf3TS)bzJ8~(jf-x* z(!+1ZQpJ^TTURo%lpEckvxYgH8u2wFOq$w6jeN!3WBwCoLyQ#^Yuaj-xJx}Zy61a@ zz7}(uMIDwCYK~hfy`XPb4KYkS>fNZfwIy^;$9=3@UF7B8!I{8N4IvSxTX~q%+)|h_KyI{;G@`)2vj~=GGN!u65*jIyUo(B~iJ+uY zDnGAFYU|^Tv}a^SMT)lXM_xmG31(NJCG?x4u|J`Yq_T6->-xq* z?Zcwja&RfOwR`tmq21!h@W`|)KgxP_jLYb0Si_zTXUF zbfEk`#~x%RGCE6QSbmBZf)=i(e{6djr13yCAj{-mu;rHE_dBEz(tmo_iJ0;Xh$BJ3wJeE>WjcB)!x&A6otX$Ki)gx zPSKCT61d4^%vZR9c~4-acqZYoz$I1f>B}%~p%J;BR*GB|EYl6-F}(|2o(V&i&;odz z*yBPy02}}UxTxw!5B*mUw6u{jAfp0lyq>BuThKP&g{NB*H^X5|p#p5RQIDK6?FBx= zm#+$Y2eT|t&um_1#lFBlB@J%FZoK>+tTo7xftctJ$x>^fs_l;f{rejJMu^`|`9o&? zuJU(i=HVp@n81opm;0GLuk@%4SuGoym1OBp; zOtM^RiEc}|=}?MAqJm&ST?&b&|(RtMv$_K&*?%iHc|64A#sH0Z)}k5%-( z?t@#c8crymQZ!ueH7r+^>PGvSig)Y`j%LW0%u&X|-|oUH)xu6(;Bk+#yZ~wD#9+Zh z03VQ|2=y?-$pI*3camEjOeA3Z-j~i!@5ZFUeHVX?iq8O%wj@jKWPkQ%5u~<~B4t7a zsk*BRW8rnw`5-N4f}byyz(sNq{6Kt4qWeAHg;hIfej?BYTsUmzq(gl5PF*nL<;s`~ zNEZ^}%5x{MVID2#cga<_a`dd~XY2@HA#$-n2)#d|L4JRO(C^^b+|B?a9J>M?CAyyc z(V|y>WFJW2a{_2|nRz^hpeJp|PK^j)aA=I-iHV!9Cq}F}Rh?LgG*f!9RDVCXh%tv% zNhi3I`y}nyqRy<(=Q~@|H@}hUAMk4j+}fix@yDsX{5?Ux5O>u)N~3WerPFfM5u#v+v8SME;}1n2cmZ!HF#TGVfE^*d;-IY(<713+i@aamFi{|)M&ER@F6MkqKwVoXwbJJ8qjP)Kz&i_ z7r~;{nKS&U8O4tJZ=#FUI%P!zA(Bv6QTVT}4*d>n)^s|@J{VH~*;CnOBB5Xu)sy1$@B z-(md$bI!pg_*A)gaPl}54+3hMxR4`BR5=-J{yXCwdH2iJ9fK8dv7GamR??+hUaMf7 z-K12=UCo6jKt#3Q4SM&98NKu>>q@zi>P5gwL<0MBCj7K^6qxwaEYIMJ^Jmm*~%A6xAy8+vuUwRi;}u~r;b@nPuJ+!N2NvwNC~9;w20VH=r15(gYN$uMn%HJ71uuX@oD7IXmJ&d^1yrX?dy62>>%dyZkP3u2 z2TXlF0vu7|x1vP2?E-e?U(PnbJ8)-PcM?T4@C77BtuUk&Yf_D299Z+E~XuJ02i$BEwk+;6Y0Qz;c!6b5}%`c9QR~0l( zPhors&B7+;WQJ{PYg_oLuP;7)A@gWyD@EWFwunHmY;CRbuKGR)ourIbKx=c2aY$A` zK|#T;s^JmoGz9U8(7w^l=z3s1uzWpgwvA&`ITTpw>g&P1w81=EU0GQ(7^NhS+P>P9 zEBY$V#PTFf7)Ol~0d$FBpKF$GC9Xx{Zld!hN|>EZzuW8oB_8;}E?(d&T7%!ey<>>8 zNqdm~-gTvWL-TD}L6LxAUqO*1=v1XGwiTINJdSMZa_prtia4%{+ zF1Eqgv3h@l z6onH51(}&=4~rJQYI%Kn7v9}khaK>ZgH6%Aa`r6xnoZF0Q@JTYvFZyGM(+Jv=z^rA zak}%V5FAHTBcZtVTDZP+`S_q#I|8b5(n0-{&&dZk3=AhOK52^{4@EoPs@ie>rn0r zln~B1+82O&bOKJmLY(8AWQSneTjsm!DefA{xdc5nb?5kqs(YeniBFpwf`a3bb#^(S z%M(>8HN5wgGA-Nw%XCeRQh8?Eo!bw4&AX(Jb^^6l9M;kq(lD5r@g1PUU}Ro5h&H9b zoqfqoD@){2nQz6evIb>Z!0?E*irP;(!^+qqn0+SwhKDG#N&F~t$}v}`qIdAVMrhG{ z>Y#$(5HpwhVNy9u7|xZ5j(5<9I8LDj!?6o*UgG^nK0w^JyFi*{M*|V4TB1`RrGr76 z+{1H=y`6g8g5WnmE&x+1m925U6o-ZZ<<1;$9416q@d_;>e|fW5AP-xDiOA-3`6`>z zxCS(^7OdA@tpnFjsuNhL=uPY9hPAJegsMziSCcR;2x2rMo94)qObo?vXO)9jA1=%X zL7E{`C~EOEt#gzZiA~!-yf%X7Y`(Qw9#M&O`Q5Nya9vl7(eR#Hs&#Hp!gy`?Pw(n| z2*97rLK_^Egi7c&2ys!MMHlw22CD=TZ-@ANijOSi6m*I6}tv2GfSG+~)B?G6fBcvi2oB(zR5f*Dam1){4165?7~ z23D(2L2GUSXQuhPd5h&WmJe+qW9SB{(y2#Jhc+co<+@%&m!r;VQJL3>E> zhR)!(7sA=O`3(qxGf66z@fLyjH==&A>=Fgj=6f~&H4ugGl=(!v{OLZb3Gq#K-rN(7 zi$(21$>zD#QHSQRdqM83nRCJc<0GC77x{@nKatd2ii4Y|z!xU#=SSKwVV*EozCO?+ z^TT}wo333JIwL)=-@Fl9j`ZPa)hp#1%zPV}^mdK4@c?Kh*x)Mrze9e(x~DKmK^^%-Ji)#}H|f#pLX1V`n$ zPF(iLzB&baiW!d7)sCad$e{S&6Kv^d8nR{;TV0c;GVdXJWEiWWjbh)oh4O&eCtS6B zQd2$JU}manqo@S@ONxF-wKtI^4GBB}mA_59+%NEy`H&>%3_IZlvZ4CVY--K-?IQG2 zj=Y@fe7&)Gs<59itjo7%cjZp|NXU`;;?Uyl)H^c5c^#-&k2cz99$|Ww;y8VM2n}w- zAqLh45oUR+e&)@zO|?I@oY^gK;a%8#<1+#7>-g~wk2dy5VCEqKfnAGh!h5HyV3p-L z*cvcX&7ZXXMr@39FgxlSfimNK$NGBek2 zQ|7|bpi}yh=OiN23J)$G!Bcy1sVsWo0pI)gUm;UCxEihFZ6<|pvULR*1afe$_5HfG zNs3>vj^^6JCY)L|jS!6w++a0((Jwl2Q;xR!4>n1p`@944?-fTA3)#`NbV_zcM(t_K zenw#MhOSCAD?~u%t?1{qDUs3m^3FM>eF8_vUO7;YnfXn(mo3v7x@FndwFaI&SKBZ( z3jlB^b*HdE>e?RB*x|p|N&tGc!~7*S_F^@)%Tc#8X73;ep!|LWPmJ*w-*H0k$hl;q zRl_ilm=>^@F9Rvg7bpemmA9$~U8@lV>-VM|r8xoM;PU2fL||Nq?7&qt z@|p*m^ID*(-_0GjaXnCeg}@lC=N+89quj?=2znAF%L5&AP0nn1jH}JD{6dbz+9}Yu zKd@3eA}eKQV3(l6mG^buQPIB2X#17%x~?h8W>uz&?Kr0}c{o9Es)OFke9iLq2}(6cSFD0J+L$Aa8G2frrJBjO;$TA1nvviW z?q>Y*4!Y>Zip1*oWtCmc>nqKgN1u15s!8O9B1pW!VhI*Yd!NiUESGm`NLW|Q3Yg*H zmH=iSo1QLjy)u;TwHntpRH#xti}LE{PiV={O%c0#^=jGu-qWS6V_PW1=UxtrL|EV{ z?$!27wpbgKuWa-PY{pNLYF5ndzyKDa4Zd^}Rn3Xg8etTKQ92uDozf(nQtl_QwVAbA zqCQ%poYZLU3Trrh@O$*`V?Hc;gDB@w5VJ?u0c)&-C0?WcIXjKnrN01b#8<0+W`$MYse@SHi^|PO{ zLw7wSlsK(_N{z^|Av~?UxE-eT7N!F-gPc*DjVKM=F>=w?4aPlK@Dm&ScvyMRMP-EH zHLR&N3eggtXOh}?5r$QZzLpxxGNWA7j2S*Pac>?@3TU%8M)S0gKHhl&`eZDw>=PoNUU)CX&$DZ9>7K0Hjflu4@2Jpbg z{uCik8Gd=Zt4#0998&IeZdz~?x4Wzu44lBCZ%}1D_Hhly#qrzmXQn^+E@?8m3c#xl zC2M-tt7TOz4aUA4ws6JQGWkyp(du(ASqU{8mW8AEa;YBciVbsw%Uw}ov>j{xJHMRR z$mj`L&}sd*d@=zP$mmJn=vspN8kWM~qwek@urvf)JwjMfwT$xg%^uC<;pJg90D-{9 z$p?|tvM?CEA}gjNjuuiqN&C(o-RJ>VX!b2i39IM_ue}!ia3>f7!Os`wzuIIyv*wFrbAllb&F!ETBS5+j>GSAy3myHupycq}Z$m6BkMS zWL<;q zx%LReRLCN;xJ5i6xX3`;@1^mTH1!Hx06d+?>ojmC2w*ym@|H(-CV2}y14F8pp(-s| zPY!xJiS~T}Cu9P;p&$2VI05A7m7sTxqu^T-stTL*j+g0z1sS#(79B(=`wL z(^v1ohs&fVGea~^j;_*K;%NyaCx46Nq}65lkkfvM&Ffyh?bcLp8PL0Q1TnFw5)DJM z2(81fz*KjrM?$j4YGpEq=~sPyV{Mu}0kDd2J1tPB`f{H7+RV5exD@9xdO|lr?mjE4 zpukXHZQPM=dNl$Oa!f$Z;&`rbC$IZlGs1pKa@Y&@H|oN3TH&*F$aiF;1vY*Wq9C_C_XI+Wk6O?#(>C$Szywp%Kh zDa(WkW&sI0NQbQ>h$U`ACu6^1zOTNX}Mv;v9Vt_OpZOO(9qC02b&7QO?!7}>IQF=i{g2&V|;z(o~uKrZkHba z9;S-CO8{0-7Z~(4_u_Qh%0mBcb40phdwYA?{qcK}#b>;y2%_;!v*nC?N9q1FL`l@f za!J)B%4&I0xVq}L=C=*jJmG0FeP$-69fED0YKMp!G|Wt$1+XniS=m`Xj$m@4{?d(x zgS>66NcmSU+tn<4jY^+#nSDz{Is$u2rMlm}XDxoWn{NGEiQBI%;2++!b(NtN7NY+B z?d_i1j#mdSw2*=(U$s7C`pHZYKGfQpeA4VXF+XK~)fotyX5w>ZQFmUDNBu5c3X`!c z8(7|`$~=}72A)3V9N`X%5d~BqQ9)!!N5>y9>vtxb^3Ago%HV9wnXq=1--9YGaeO1p zH3GZOf&gyacbBSG|FAeFWFxieTb%q&6U*{I$_JZU*;^HNzUE>O(5UMtACtnr+h+S0 zbyDcT!+qMyP4*@kD3oQjABoptte(5fvo0u66On|KIV6Cz+el>uThliNJ4HHxW1=RW z_ZkTMDujoBO(01#uxb6 zwRB)BPq&{zR3m>siPXlUGBPx6QE0ft-DXaQSs*GtY&|Sd(AG z5A1t!{H8wtzgzWxAD3@CHx@qGpK}Sq+KBv7b*P z4`X&D%vLUD%elvSTUwD?;vx`NF`#R-i9qXbeS^w@hH+7={GI{-@IFBFK6Mk=?R}#X zl0x0i4bbg|-kTm15kPZ9dZmW@aCknrY-SFUwYHRSQ>^AoD5ae5pAI6R)P2Z*JO)u> zSEwZebWx&}t0542kz*!S#^{9AF|A^^dSPdN^B&@oL@k@zptmMts#wmFDr zD5$lT@zyeOSTQ3vPCVkg z&k|VGqv{8zJel+EWywu+uNo3&P?GVv%DXe=;_A3c=Yiweq1(1|?cBo$Txc%}@O^S0 zA$88251aIM$`!2MOjR6p3Jjx%{q!lRi-bPMXQ(oNT!nDNzy9}sxUd=D zbEClhs7c`PA+G*@mlkx(Y@$bqh8})))MfHrTt1j>oZoqAcXqcmTYs)A#Ku?>znpXU ziT&22{SP1i>)%w}IB5q>h&OPhKHZJ0esY&i!~WN4mtT<*VYXH7R?# zCeYYi6=tQ`rT>tf1?wcpERRq_`zm#sbJQN3I`t1`fzSCB7uTTd_cCnNYx7cPTcJgy zXtqi4IsqNj5qq~^HM{72WN!Dgb(}H3IB4obk^trmTCZoA-615kCN`~Kd0_?rNDJu8J_UZtmrHk>?Nm5V&v^9HK{Pnp1av| zeg3oW(9=lXobBHCa+Q$fb7oDCFf0%o>(ob^n!q8JvPCybNRwk zy}keFl?v0fleIW&5>(u7$iabHu6}9btcwO3v1#g5kW1ZH@qAT~J#LmP2je96_GC7v zzu7=E6J||n*xr>JO`Cu*+63bNnF*w5Bb$6l$+b=VrWiM~BsfWLw$#YrHYg1t2`*(iq@)Gj7h+}_IT$)4@&>jNCH!YHfsw&?sYpC7N;wa z`$T2^BEhp|&}DXMb@jd)4=v$ZdZ7OtW;!_Em%V?r44}&Nluz$I`A`g~11eodw9=ulcWg&I<;M>(xw7p}iJb`w9@qK1OO(4y@yYg71vlaWKXeV-;0$ z_Mgqg3rRq5bJmxJw+fpBOZSGGSlu>A9?27sMrSt7?L#Ub~C|sut$+rl-zrMIyEi+_S>`qq><|=4l1;~ z?2)^%TjUklXKv_r=jW1t_$WFu8h-2JG$9RMi8~$y%{;zLissb3SuXj246t}TVO1f1Ab53!}Y1E)?T22p) zGMZBka3Isyk%qWmDA~p^ijr4!6F*?-~`=7phRZqEp4y)PdNOtKqaOXTFruiQ!k zdiT3beg$%dDC7K1+v{1dYOi3|QG7^&Yk$GspZfTIN$(#m^v4DBRALZJZoyoqv_RYU=U$B5qxy6t=6dwm53J@0nquty zlQ;tp%?`6cE@Qg(hRaXikm1nuYe5^&6(>GK=O|lNy02Zjc=8{*=>E2VQ-r3?pYf z>)5@8np`VW=ZO_8GYwFYIlB_(x8>r|K6jo_!9y!sjj^mL9QSF=t2M%^I^EnGPGnW?X7eC)!)Og;{c7hjWb0Qq&uE{Q-scV*KkJT4`0>5^1a1W)+H#WUis_)y1fK{x8DDBna`faj zuBEm>NH&wT)E~e!js>An8IHX}r7k@uJ$t`h@x!^nu@igId(0QI@aEa=EEQ?! z(htEb^`Y$*)v;3dY_Lx3my_Dc`qW)Z&(XJ~g|1zlTRrW%;z2*0yL|Ga(M})F0jw*g z$fU+F2<)3YA9|-a3YT9RBowUVzu0Yl8{4uQrxrB1M(!$HapF+TJ!dVX$2{R&tJTR$ zZ_jX*09rd=5eW=6Q*mI-*PEv6jf3s)qC3k@_m8caNZv5d*?Cd7iLWk=FuvuhNla;A zbYMom(Xvx!f=i(T5uvX81Q2ct!(LDmCyDMP==|PpTJ^31W9N|{W)WqM){DEE9Kw>$ zm#L8z2#n>;_~KNB7(q#?3Uq_;@lKVR3F6GKZy!v?WQwEJ6&%}|x)m?Ef8JztOd0n8 z5mpL-0|rWNrYLDGC)+c+I-MC_^{W%s9r5_`GzBwDf4Xf1t1h|tg_4`|TB=OQnU8ie z8&Bm%Qx-w831CC|zGC}k5&wOHA+^Iep8PGu;%w`K@(a&v`q9N13y-E!>WD+S1t-O4 zgyYFrSUab??#cH&k^V^yO1u+SMZvD7?s}tzv`N9=4!(9S(|N}6V~A*4x=4SYd&JJ# z-^nYR5Q(>Yv5;Q2?O`(!iSNUF!2>sU-o|iNY3hv5=CyjJqUTh~XZ19UdTroVp4x^v z3YaH4y)FzlaLQtR=*zJ}aV5GZ5U9VGhV*2nwh?DyUH7>z|1r!8(SFC{0uTCr!E<10 zYsXLG!`giqkiCkBaxx)z8!d~IRx-;K@2t-vPCf#ZOeH9_4v~IvLLeAPZ_pk4J67@@ z!h{}I;s<4dX=zHgob=a&!awQ=EktsSR%*(lAJ}tI4u0mONRmZqWMdV*1{^vA0!NQD zdm3^%r6I)3cMNnkqh8IIkucgYR%DK5?DP{BGXypj?Vnd8+J1D5yVP#b^YH!Y#e#Pj z4}@?-eU7$ur+JqO)1%4lYE)rN!D&ibQQ4$S$gJ~h9h+`jROR5CWnb^>Q2oO0f3qS# z8K)GS-n(Ts9w5x7D2G;O0Ue!38eOuM=4KkbZGUy?2@fVMD2N9R&w6E#?jC>RHGuGR zTWiX^LXEL|s3Yqy>`T&zm;%>B%ezsqik^VptJZy?gNJ*h=dSAn^GzwON73s` zXD4TmyQE(;+gG{RHhoycTB;SP9BP%Kh-iC|bpLsc!_~qyGDSoq_zB%7Q_a;Yk*+>? zJ6o-=d$scVZwM7hRq0w+RktDF$0!E`&iKt*6w-m7#DbD+Hj7uOP}niz0>W#)*qo#$ zSB?ZbWvMkU1;qNR)FG?X)7|kO%V+A$G*x8?tuaWw55O|G%bca!p&^2C^|%+8s3zTy|fh)hDYth)`Io z)TU*9wACH`&cWLN&$~2G*^DHM^)b`T8&^iv_hNpX&*b)a`0k`<=S`;@zOBA#_iXeX z_Ekoo+jJB1m>7P8+DVG^dS0C`OYIWQOlynqdeh;2TWhBc^i61**ru$%%T{m&b+|;*~ z#^0^@gmrO0RdkpoubNg06nC6t+9N@!5|caliI7XjtNAQ{i`csEUmLPe%;VbAP@SAO zE!z|1VABl5HtYJ6;bWDM@%tK4@gLNeL@!fz-=N2r8;YP6_SQkaJv(}`qVrQb>KLJpN~UU-OFE}o(kio|a!#C>Ja z@{{%LT%yfX1^WB|J}}N}T4Y~f`oO{RBQt78aZN5sx1o`=p=VR6-w7>LLFoA=@ri0; zSpgWML9F!|?-fwjfa|;a>5yjAi_EikKcAYYB@E@Hb3(tM#^!0D`}x>q-|LeZh-|x$ zPb?yqM|#Gnvq`tsXB*9v4d}rw#9XF#upHmxMo-H(A$~UN5x}A>bx$57`^v6AVq6|dBciR9~GV+umW{ z_L^<@-n?D%2YBK911Lk-0F3<8+SudMYcQ&T=a zyOmm-ACwT%2o9~N1|P0Qa0#%kz%dRhfGBf?}tR8bK zMo739h+&qD@27bx%d$ExW)s|iPk_+Ka-J8qwl^GXnE3xBGo z!lyW!HKMk+^Mv?BwBD;peqQZY)KNmb1>4_O*+SAJQWcS#750R!Y4d1#UtO=q#-z8l zUqL%T@QV7js4H+#`>350^Bxjc6G%N8nJUrV9oc215gl(==xnPC2pTpH60W6KL514M=bol&gv$l$aAc?_%#6h zJ;&S%23sJe0&yEyl)o3Y3jB-@3se)^&E`;fD5HQ6c-6&XIn+o24FkM#?~M?fH;Q-NG_L#b{1R-7#M*-@%_*VY~O+E?$n zg9&*K>4NbwzeA#PzdP*N%~9R6(A7F4JR#}3*FM71#gk{MG!eYCi^M{zYSg- zUQGmjN47_zMvR_B?ej@^D&G88{iTg|W{O2~W^VXI6|3Zjf?BBzq zp5OC~>szdB>Oou2X_#px4KV<^=nw|Ryw~%Cito@{?B(SDUkd1F!I7b=06^G?FD5I8 z7|modj5i~;H5@b_Ynm0ABXadejfJCX)p8qrCwr|{-S=1G{t}}Ju(JW;m{v2PPZA)X z8{*#b`y;3g|N2BcSm_8?Gv3$4?Y%fr08suC(vbVB0C@QS6y)z!{GxnwpI;c$4ai%X z*G--FyGY(1=Xsp&obkv0Qqy0CE{6}-h~^h6?K86#Y!13#8Ohzd}Wn*Bk_9{c*BH0j}` zDL!Z(K08r0-14|s_|#|rGD=9zz9!qu{Jq(j=syAiB~I_l%4CgQ*LYk=t?1kxNZtMt z(Wi_29+YAy?qfl*ZmIq5@L}>{`}#J^!0Y?^?ZAtt)PNbu>YldP=Qn!9>b{bE26E;NyV$(m(eRuA#Of=*0F z-JS93cLs=y$@)+*7@XsHR#njnN&j@96v_;(XZWlgsdYo&tR)PX0Y%GTx6Tt6$tt^b z*cR>rJtW}@AAse(EPK>_Y%V?isNndJk?_uQfpw(R0i(D_R4QylUAmL|Pnx`4<{n3+ zL0qW3nT=%~;T^48QPnrf>YPyi>Gp|k_UdINXa2=X%dLfT?dSfjr!pj~gOc*q- zpV@4}jI4OrCnS9}6<|G0t5_Bw_V-0>7Inb|Lmt%lx^33D@XoKDk~`iEkhNcrVCVkm z@liY$PM=U&S%tICOKvm{alBT6f@JCP_9>;K32-eL<7Je4vP8IHBl5G!IfJ1P*7KXC zFci{rSIEc`1!^Y}9lhxVUoFRK@cs7y6fL3?MzJT#3Eu|rmjbw<&W5`?H;`q3x=x#N zNBFS7Ex}dQtU+bffYGrpYf6gu@O5UJp&4CUTSLL$MgPsFT$EWKfO+@rc z@W{2%akQ%Ay*)u98j7QzLZ9-TKa6Ak0fHft#Nnulag;w?&8PR1*cq{(6x*z_Mqfg)0W`a7`i=$ zIs;7~Z?-H>lbISAlC82mJP@%xRbe6ZqbMSC>)t1E2sYi1MN;tG`sV^&8M{|Qy>G0F zKK?#%4n}7tt`yB~R6NKIorwGFY zM}ZDT**Zlyd(J1?{k5~fl$0GzH@~*Co6iSx*LjF-Ur>wbgJFXmBFHNQGJGB~EpuWS z+nC)MEGYDffAa(vDI@9p+;TB!{qlNu}9HrdAdow_J=71}lS|*%I z{if8q3UEy`+d9c1!wxi4lJ@GyC~y=XIGE12x@L>qj7^8NMop^yTw+(au{V?!>X+@U zvN)@y@Y2sU>yy$H!%+A_`@LfM_m%1=V)Cx;a+quHk_@QJMJgpBXS&Fz1mcOUanR)(xmKX{Ox)Q`a>t<%#U^tvyf#Af%j-^Fi7ow)%FKSASs(qpuG~OixCoA6rKh@+;`x=z0TjgvO(2k_g&pl9 zz83ptX?XUp(E&0Ur{=m^$I^B0991LzW|G1DU;@9jxi*e7_Q(%FCdxfEQo9oFb$euq-B@oU+^Mcs8BJ-VM7&F3MZ`F{i17s_|>9uYEN#|MIcbf*ZX6t zrsqt}oZqAMxQ}EKpv$@oX$yee!AtMWlAF?yyj@G3+W2PsW`*i4N>?YG6Kd3gr?yh2 z&7rL4kE*dhhdk;GV>AS0Gj)6;ys${8>YsEEOas9tz!O(cTI!7%+9UKm!!(lmgnD4C zQg?E-$zQ5vwtk=|hF&>G4q@tFbj2&RXS%svnF83oJ)LbdY1a46%ae}a_NFO+t9CI> z=SLvj$CNAKcjbO_AIyEjpb@hod?xjs8hxh8+qizjV}hy_f}ty4{!~womw6qlWrG4i z@5P=}hvs*z$+>hF9v8gi+Jm_D?C5Vd@*B^-vv+lonQ3vXytyAE|L+j#2~FDaBNZQM)*0tZ^pgM+Dovy z@kS{@*w9r->sk{y(fiaao9@r`>0PR4T(hP(qC&9SJr#`5x+Y;9(he>pMcRE}q70n^ zPK5v#v^UfS$AO0UP^Yu>)OjaD`An1y<{6FSXtaHXxi z`tI=9;EUG@O~<2QjA;S|ZJX_K7%QFN_#CllC*X2F1$q=`XEl9(jrn5?jXynj%oV=l zYvOA?T{y{VI{t=yi>>NDcnje8Z%Lc@{EeH!``)64KM;ZUtYvJq#ec;AkQuv&S#$m8 z${}VtM8OR4p!qT-I~$GJnR}NqKPG2eDZj3&lO}oTX}c1V<;6McV?7}Yn|x{KY@su3 ze-ZF4{DZot>^xfVRzK|)roys#29|m*cYSO0^SGz#Xm)c@ErCX6A!njzE$TPsaUbPs zC{dvD7O~l`dJ*kMVbx`mq}S6s$w5g37mOm9yhDsYbao>i_awMGCj>pAW{ax__O~5` z(A#aj`CWN0y3)4DYt5qo_uUo&nJ!~V*w=*xtVk$Mc1^*fsV`VFFEN|WMzyyX&uU3M zm_vi24829>x32V_$288G+7m;rnis&q>0yg*XQdr0UDPdvaq2AVXFQs=xs>i`ja0bFZ3Ff|P@!?G*zTk~ynmOMcis|n58iT- z6GZVXRHnX`)Kg@lIvYYlY7>46ddCQzA6_byKNYrP9{u;RNl!zTTY0`t3r1*a?}m*N+(QJvDJ5 z{+IjD<@fl=@FT;0L+;rTwfSQV1O^4y1W=;rt&sr4B#C<|Yl4d0yY7$4Ro(tZfRC{vz)BumnPrf@JwT^>=$0SGduX z9=&U}pp-p&%SjJka4#hoTs7T{MauI%7h*#7csIJt>v&3XAxkS=Wh`1HWG-i;iNKLB zX{qQY^N^$0>(FTjy%GcDy2U3Pu+SeLRuC9&`J{Tq94zr!`r!8Jv~*73s7YU1ML2o7 z0_Rz`iTLev4;c(u03qJ9JK~jke4fonv~IkW2-~gJ`xJ?0^A$pA3;A{6!-4P!h4Dtr zMr#36BC4RSN=guafK>&yjdc*M0lUI^E;~|SsISk`Qi($>GJ%qQ23ISb+T>p$JuE?6 zkb&>spg#IU{QQGE7X@5`Fce94H#(f}k0LJgfr}w+Q0}QKw7mHc(xDYiKs^TZY;jsg zsxTam#zL`1DG0JNSeT18F;z~6tI-QwqkmK!3LpY?g-zC>NaTN7wSJ#Q* zow|ItVkH9~mNNNZjD9r*W*d@}Aw6b_NVv&oK)r@kyjtp{zoS|hjTaP{QOrFc@J+IP za1viW)~Ljc=4eOL1W31!Nro9BtF(rybk|cH!&XvRuBqfi+yZOh5-4-^SIcyoT#+Oc zw-UULh;|~Xo>G(?JovtKtqwY(ZmdNI`r|5gd|sa%F*w+UN9Wy_z{uzN2Eg7n_8CT2 zS7{OQPa6EuPI=$B6pz6>zIGo0K-24!{-T${>A=$@MSg~$(rt?nBidQoOTAx4br%|(kYPqS z?uT=@Tcj+n_8Y&$**t_E{d<_&=0KmWs3_RAcw+OHWnZ#zIPS>Hl1#Aexz;902-dZD zjg#?D`zw{gDQk{yZkLHz#9hv#n{C4u3phIqPR>XMDaI7R3RvNu!87HH7T;M~Wi6aS z7vY-lC}w*5H6bpllz8L~nUgxU1>I~E<-Ac!Vg>`YhN`tkxj(seFW!}H6-#}GV2z+n zuauGvJ@DFmy|SU#@0TwNqFj)yVwc#Hsacf)NWBE{iI>TGYrt`w)gyZ_+iyTt*d(6c z;jn`A@SJuzF7gvHl5nNDBv&M+z1t>Z5R%CjOl{8J8G4G;^)=9G_eDX;AHC$`?}i)} zBzg(lQRh}G;p=LUwSy7shoQsg|c|3VV|IIkaoh;LM05KqWfDN(_i%GXFeI>Jel92KYs25 zn1$9;v*XuskU33Fl+B3l#unq?NBr!#y7+-HiegI}06ELX0{l&ewPZO$@Kn*7yB-4F zNlX|QN*!Q!fxfIeq(4Z_(+P2n-wb?S{YB~^98aL595#Bte5^LJx~T{W=YgZ_L+18Th zo9%B^T;&rm2n?Bzuyuvz^>~-(?hoSG)am?Fp~>!F(6!&fjqDS+neugFH17xfJnSCx z+dVaK7OruHUX#v?3)}K}?f&>dapOA5+;LrJNR?sot-USrtR{$WxJP44KAEW(jl;j~ zd*VkA-7(YLc6_}K+hL;Kc1&%BClVVMsk2LN0@>L6>xgOIE2=f9B>szA1M%tJxF!L9 zMUb4gZm7!;C6_6w_@a7oApw0&OjGun$(h#b^(6T)abG~s8R%iA=|j+j{MC>x@LQ#l zUBYJ*3DY;lcT8tpQ%4u06Ws6Ag-x1x=yD!iYkR`4lzobblX$gb>^(p;v|=hDBjd36 z(_4#58mD|+46@=DtvCz%s`4{?5IN5MF24U}7o!imm9C4ENDAE+h%E>UH~e|1e`gvQ znkygy#YQIeJ?&+iIul!X_DZ0rtuDLNRUUyPv1(&RN3nU?$PUf!FKyW%jRNC`wIvDS zsn+=&UUf#;t%iH9b39qb_!Sw;V#4WrF6^6KHMx5@r}T>)QCc;KS$p9gGmuH|>thc{u4a9m0(XJi|hm>L^%OFwnd7&HKB+fuVRs z?iFMNuHdUDLHs&ljJP^E%obj>!(!vp<-bBk3QY+*kcoPqa4Ul(em5igxpE7(4i(nF z4k0)%Hg#_aDuB!_Yd$V!&HyUmy{NRj!LJ}*<1oFBdJAYcc-DZkgSz)>^M{~;Rf`** znWYJfj+5;kIbR~$BUcq}mB*zP+TyP)ggN7$^@v*{Jr_v4a88)Snt}~WE;0be5ani} z@4VB{_kH(5Niv%CHA=EtS$4|gTipkRgBVydr@Jk(ZEABR8P;?v3Ebji$H5teE34^T z$1ms2_|tcB7h(}nlnz#HIAEPAtZbOe>sH3KC4ZG|B(*cEPE_3kyBs@_{hHs)YElU? z?r8N3Y!9;v>z!{x7TM@2oj(^jWQ%$m$7Hmdi02Nmhwyam>!+9VMmL3~YuRz}L#FF9 z^_A7LKn?G0lgdKTp}*4>+~!;HL>M(5i$^WeLnqG`r|IEdWEik_UbbD0NEEMhz39`A zFb+l#9bdoq7l=##W%oD}W*c0p<;#?E-X5k7z2=z6Q}zKz2#VK`X4yQq)8y7wB&jk z?5-%0QQ!EZx6*a;eB<0Lqu=XrUNb>Ru3sxKzYLeF+s;gXE@QYzY)=0SWno+o@1^y8iJ9P%`e-vA1GY{pQj`7H@Q5KQg{8Jkgy$8fg`mB&5{! zHu5?5(*f_3@dQyD*4S`lA*=OV2MVtM^3KumYxA}|>?R3YomLAGmkZF`)^i`qv?PPh zx4y(mxSu%uM7zt1d7@n8YYJ}2UjX5!g-#jqr~`WccUQ2 zL`<=HA`wuR38O7x0fin!hCcsnPrS4_i2VRr{>Gg3P~>epzmTt`UKaV#1O?4Z(!LB` zUA*+R%2=;aV({SPmaPg7adg}|B#QI&h&olnkJZU~k;ALhT(doDmw3|c=g4yppphxF zmH`$a&(R;HiF2m1FD_tg@C{R2Kv^00HJH#&D~^?bR;W3Fs`bjV z8Q1H19$o*Xp+pS~N;>hqp@^L>=?yM&nG;Y<_HOYQ$l$$kK!7ck|Wye#lx z%3-5P7f}%LHPzsjV9l?%kt8ThzTF?X_i%XN5>6A zo`q(F#QoZ4{P1#_6$TTBcHG@YZ_xTQqLxztyEyvC_mNFGz7<<)BE98ctpI;wP{I~# z#b2{PlnXJ{`KAyFn1JSWjeA4Q6b>ei;F{PXXYMHs$vEaU;bILctC^l-?n{*ZG$lke zD>3(VAI-wq0JJ#fBqhA_`+u4B)h!!$2VY#(L9eI+@8^?^ban<)C4qZxZ;s$vt67CF8rSL_IQnPd?JA4i z#m+`vSS9+))7&}-qti^rWMx0iux&YD5$69jSps%I+R;zeeoK2H13=IBci2f=o#w3i zzh+4-ng}%s=%Vr8@ro!3-WMN#`Q?w-H?Li>(t#4@5SXdp-lb=w(@y&8UGWB6SNqDR zYguR**PX*^Q!KC1*I}B95Xo1K5}*B~N9g^{U)5e4h6;$C_)rpOXB&Ul#=>|zAE>u^ z1*x~W%_|LhkM}A-{FPFka3o>*i?>yImA6xfLj1>>E?ZWK#Y7}=#$4W^B{<|&oA2z) zt?Mt=@)E^0KV($ww3gW0dv}R8Jv3_Z9T-~%+%0jdg_PRWj*xn~-5HdJH}7#_b{y6M zOaH`oi)`s9ne+AYnVTwsfmO7FNqJ)ruR$J{x33 zSVN~Ol|_n1Sfw@xW|8S+!!WQjj*JwIXelXM$RM_V=;nt{Hz`%oQP>}M&>-%kIQaK3 zFAH`}4+~^s@A^*HV4Qe7#)@_#)~R^go+Wg{)YlxEUJ7c!0&|ko#N+^WNa9SiS^p$H z@*%E3W~CUl>x-NP*Q{>GO0cLRu~R^WC35V+m)pPs5nSNr2H)4{hCg;mBCYJ+1`ICE z-L<+Mo9uqhuh-kg>y1OX*FG7{2$~znrL-S)FaN1%q~;#;^1@3^@>wcC4;Wm1u8)f3 zyaR5QdY+q?xg_OpaIX9!J4|9D8}Qk*us4|ZX!3U<06E(*3AGB{9hBr`##X!hW+EPa zVWt9dXe%X!xHHYIgIEA4WH_TFPE!qc4e4GweLl61?%?wgv+dD<2%)cT@7F zKusGFd5n@Sb3TeSYrs}GG1QT?W4$4+^&S>oamLAtt%%?_V9%Y`5+$@T6?F@fb2gET z7WHPl#fYvwAVW-QHQ>U}<}A4?ow1@SU7e~%+9pq+C!N?EXn>?rF_B1XIIDfWvQMwa zO)0Na{ZIcx44T5=_2s%iZegmZ^P}ExgSG7oaBQ-Gy`p2sG*4_$PEhaH9(`a_C zQp}rKk+&Ri((W8FRj4M2|3{rj-C)O)e5fB2b6w=bok%z8Mn zPQc?w`x5n3e3pqAW>Vby0I`U!xEVCM{)DF+HSo5J{TyM|w>3m(M-_fUz%f|}&8wXNM>kM=uqO7bT^H(V@$vV_OO)-Ewpxx1JrVtjb{Y5IGido$Y_@ z!J9G1)PmFN8O9#kWrafB^*U-#t{lF>jijuvOjIvY6kh%&VfCw$!RDsR${xSM;h?!y zA^ux6SL=8_aCaoRvNK9WrW%oeqs6`hK_56ODdn9j=H)2Tk|$Dk1ObUPBW6bP3G()gc&zctYmjd*k>> z=$^*_z)L=mSfXz)3z`>8vbKd~Km@=v4Vx&NP{MR_W*$qC`rsCJ>f1PctS+h2&a73c=e`5H zJDRVvT|&vQ3o2yYL*$k52P#M?fx0>su(H9F=p((sMQY}XZ*fy3Ios)lgP~J?Sy4KU zI_jVd&h+}ZZ4M*o!$o_}C(zd6$x z3t))tbyGxN`Af$qTc^YSR2d3itvg%DkAt8MY8N)`@toBxEKqV#hNlwbx0%gKFjd6p zj3RH0W8h~^;%vbJ9V`bHi4r_5RTE9?A|L|9&hTXow29A*6_6 zS24-VOB-}RV3gyE8Q;}T+A2-XNqGTlG$ZLQ_3H79Eov=R_!shYDcZL+S>4n-_=a>p z`8~sc8x+*CR|N*WhC)`yRT95;EUCQILK&Tm@&T z#3K(|Arjos`MHH`gr~d3S*@!%7E;Zo=|dL?Q%h58bZe_SN%ZyFPwvlcod6>d%H+|2 z#X5U0Q~y`ub$8Lzj6+@K$9(jV)Z55-ba}54a(n8Hd2xEJ;R*)Lz5}9e*`>6W%sH&? z&U9WfXWiAg#B12Ykc-|OW7Ym%9!KzT<(^QNqucw**G(xzCMnC$Y^zpL;VMx8 z3Ahr4Q4yh>(f+!#s;h1Od)6bxwjX^gN}lRsxlB9VewF?xP6*pYsTJ<( zL)_Fe(vZ|TN4g9+|F;P!cI|SmK|Zb!PUbM(l6hD{BS<{d#qT-^~AZFDc2lS zzSr7D>)KnIQpY`k`^>ekk_s z2p^s$58FIHgar%@qnha5N1kJO3}5*(HS|y0^4z%30DWoXkwW;Qj8o^e{OY<})I+)D$)me4qU!5UvtR9o>v-CPzK=FR za4-Ji@zE@(_xiM>gf-u?`_oBi3@;I&BxF#n*nwn{YTa9w+Ysqh=JLsXl_NNgy+i!1 zW`e7dUME{Zfhu_bx2u0H^7{vO^dK1@U=RhE?+FKb?+epl+wl$TWs8+;1XQM8Ci2cH z+LiLM3HVmqqBnQk)gZ7_s1#6U=m9QRi*@~t*88F4*OKzkjXs(ssNIPAyYbY0fkt zVG3r2NE!~d_}o%8|C^-7AAAY1SH6oe>ASJX=El~PN3GCWS;E#poREtWfPaf?;c1>|iLAmsZU)#dQRD%|l55O%4rETz-~kf<2Uq%?U8K|bYX<(=j8j6DS8x4rA zM)Wjad%-C*O?N{l94H(P0~3NmZ31+tYKyfxkmyN`i#bm zxnYjCGxgNriG+t%VO0p@Uaj1$0JQJ{8iOI!zbJMIIG&2(J~1dtNl<9O-bG1&v$y(( zdzWf^LiP(WMEp|2YcxGun?ff2&GQlCdf!JB%_+&#hitI)9!TEVV%L<;?&;Vf!086m z^P{0Ff|BfSMIe@rxW7v@pU;5%SmqrK~PIQqg5|W6%{1Z?pChfu#qCTzgfL(W~d)lEyAI!_X zu6p@GGl)h=ah%5It@vBTsj+dQ=R00|^Zt3gxAa3yN1sb)l;d;*ZcX}IbGT61T*kVA zCN`G@x*D^SXmBtUY%(rcHpjonOK9o%Myw&3eQ!`)v>($5*brT1VS=+yH2aOdo%k@z zv!qdQHI!bx7-53{pz4%e;nVhgcnLbNGB7z4> zGUro-(9_BiGoQZqm|peYZoXc)!{cHiI&*kV6ekANSfYLEj?$=HVTmyH1-PY&s89ie z6P{V>IJ?Od_R7yyP@hCE-4(bQy?AtVG>NqngnDz{=k#|Z51%5?3^-34miAn0I!-S| z5_-S1B@T}&GOmN*)r&Thdr(}E}pe#HA&bUboJ}xAGKf?|EF3V9|7da_FoepZ;ZeY_&>*o$0^#1)- z+0-TY?uRPcEpP?2nm09@ zMF6UuvH+1S;Xm$ZuSm<3m3aT0^^gDD@b;0ivf9b**lE`Frr?#D?csd$0^6Phv)Y=6 zq0G?r(N721qbK*gd2SPTfo{Wv2L}P?V_2rPcc{&LxS{*pbAPpBYPF8T_yP1Z1|{tPpeYnMQNKW$i!rP)z&yYkdvo|FYj62>M?C6WrUi;Qu`JPyJ>!6<}a5hFvld{hyuqZ@2S*cH;jXUjAFO zeE*+t`tS0{e{$l#8<}7JlN0~jCi-tN`9Hws-yRI`{{`5vV7ic$QDy!Y2X@W=(J=e` z@+oipvTOTaqDo6ejUP>h6NYm}tySM_>hnnb;mn~gP*wI;?cH~O#jN#-oIm+*1K)p} zvwto0egWl__H4(S`-RW02andsdB4*7*9ZOFKk_D@45@(;7xoLDQ;!GxlO$7(f8Q^b zEjPR+0G{oRHt1a3I-^uv?2&cxUi61J-e3f}7$Mk(i(Jvd%g@W;+}NOHYoaJE-x}S#w?!g&qvP*B~pGf>abf zH0>JsFl2vFTJs3`ZfI2$%25+W{ycxArE~-N>d626EdTR**qg?W*AKYAMO2qlul@Vi z{7-=OlRU5}+?^YE_BjaNr+_usT{R=P&-c~xuzryf45d>3Sk3qa_`7L*=UUa(hfn_> DwtSbC diff --git a/docs/modules/ROOT/assets/images/remove.txt b/docs/modules/ROOT/assets/images/remove.txt deleted file mode 100644 index bbd40769d..000000000 --- a/docs/modules/ROOT/assets/images/remove.txt +++ /dev/null @@ -1 +0,0 @@ -please remove once this directory is not empty \ No newline at end of file diff --git a/docs/modules/ROOT/assets/images/scf-azure-adapter.svg b/docs/modules/ROOT/assets/images/scf-azure-adapter.svg deleted file mode 100644 index 8a064d8f4..000000000 --- a/docs/modules/ROOT/assets/images/scf-azure-adapter.svg +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc deleted file mode 100644 index 057e94235..000000000 --- a/docs/modules/ROOT/nav.adoc +++ /dev/null @@ -1,22 +0,0 @@ -* xref:index.adoc[] -* xref:spring-integration.adoc[] -* xref:README.adoc[] -* xref:_intro.adoc[] -** xref:adapters/aws-intro.adoc[] -** xref:adapters/aws.adoc[] -** xref:adapters/azure-intro.adoc[] -** xref:adapters/azure.adoc[] -** xref:adapters/gcp-intro.adoc[] -** xref:adapters/gcp.adoc[] -* xref:functional.adoc[] -* xref:getting-started.adoc[] -* xref:sagan-index.adoc[] -* xref:spring-cloud-function.adoc[] -** xref:spring-cloud-function/introduction.adoc[] -** xref:spring-cloud-function/getting-started.adoc[] -** xref:spring-cloud-function/programming-model.adoc[] -** xref:spring-cloud-function/standalone-web-applications.adoc[] -** xref:spring-cloud-function/standalone-streaming-applications.adoc[] -** xref:spring-cloud-function/deploying-a-packaged.adoc[] -** xref:spring-cloud-function/functional-bean-definitions.adoc[] -** xref:spring-cloud-function/serverless-platform-adapters.adoc[] diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc deleted file mode 100644 index ca19eeae6..000000000 --- a/docs/modules/ROOT/pages/README.adoc +++ /dev/null @@ -1,25 +0,0 @@ -:branch: master - -image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch={branch}[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] - -[[introduction]] -= Introduction -:page-section-summary-toc: 1 - - -[[getting-started]] -= Getting Started -:page-section-summary-toc: 1 - - -[[building]] -= Building -:page-section-summary-toc: 1 - -include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[] - -[[contributing]] -= Contributing -:page-section-summary-toc: 1 - -include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] diff --git a/docs/modules/ROOT/pages/_intro.adoc b/docs/modules/ROOT/pages/_intro.adoc deleted file mode 100644 index 76c97c73c..000000000 --- a/docs/modules/ROOT/pages/_intro.adoc +++ /dev/null @@ -1,47 +0,0 @@ -Spring Cloud Function is a project with the following high-level goals: - -* Promote the implementation of business logic via functions. -* Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task. -* Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS). -* Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers. - -It abstracts away all of the transport details and -infrastructure, allowing the developer to keep all the familiar tools -and processes, and focus firmly on business logic. - -Here's a complete, executable, testable Spring Boot application -(implementing a simple string manipulation): - -[source,java] ----- -@SpringBootApplication -public class Application { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} ----- - -It's just a Spring Boot application, so it can be built, run and -tested, locally and in a CI build, the same way as any other Spring -Boot application. The `Function` is from `java.util` and `Flux` is a -https://www.reactive-streams.org/[Reactive Streams] `Publisher` from -https://projectreactor.io/[Project Reactor]. The function can be -accessed over HTTP or messaging. - -Spring Cloud Function has the following features: - -* _Choice of programming styles - reactive, imperative or hybrid._ -* _Function composition and adaptation (e.g., composing imperative functions with reactive)._ -* _Support for reactive function with multiple inputs and outputs allowing merging, joining and other complex streaming operation to be handled by functions._ -* _Transparent type conversion of inputs and outputs._ -* _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ -* _Adapters to expose function to the outside world as HTTP endpoints etc._ -* _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], and possibly other "serverless" service providers._ diff --git a/docs/modules/ROOT/pages/adapters/aws-intro.adoc b/docs/modules/ROOT/pages/adapters/aws-intro.adoc deleted file mode 100644 index 69d0cc782..000000000 --- a/docs/modules/ROOT/pages/adapters/aws-intro.adoc +++ /dev/null @@ -1,330 +0,0 @@ -:branch: master - -[[aws-lambda]] -= AWS Lambda - -The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. - -The details of how to get stared with AWS Lambda is out of scope of this document, so the expectation is that user has some familiarity with -AWS and AWS Lambda and wants to learn what additional value spring provides. - -[[getting-started]] -== Getting Started - -One of the goals of Spring Cloud Function framework is to provide necessary infrastructure elements to enable a _simple function application_ -to interact in a certain way in a particular environment. -A simple function application (in context or Spring) is an application that contains beans of type Supplier, Function or Consumer. -So, with AWS it means that a simple function bean should somehow be recognised and executed in AWS Lambda environment. - -Let’s look at the example: - -[source, java] ----- -@SpringBootApplication -public class FunctionConfiguration { - - public static void main(String[] args) { - SpringApplication.run(FunctionConfiguration.class, args); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } -} ----- - -It shows a complete Spring Boot application with a function bean defined in it. What’s interesting is that on the surface this is just -another boot app, but in the context of AWS Adapter it is also a perfectly valid AWS Lambda application. No other code or configuration -is required. All you need to do is package it and deploy it, so let’s look how we can do that. - -To make things simpler we’ve provided a sample project ready to be built and deployed and you can access it -https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-aws[here]. - -You simply execute `./mvnw clean package` to generate JAR file. All the necessary maven plugins have already been setup to generate -appropriate AWS deployable JAR file. (You can read more details about JAR layout in <>). - -Then you have to upload the JAR file (via AWS dashboard or AWS CLI) to AWS. - -When ask about _handler_ you specify `org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest` which is a generic request handler. - -image::{github-raw}/docs/src/main/asciidoc/images/AWS-deploy.png[width=800,scaledwidth="75%",align="center"] - -That is all. Save and execute the function with some sample data which for this function is expected to be a -String which function will uppercase and return back. - -While `org.springframework.cloud.function.adapter.aws.FunctionInvoker` is a general purpose AWS's `RequestHandler` implementation aimed at completely -isolating you from the specifics of AWS Lambda API, for some cases you may want to specify which specific AWS's `RequestHandler` you want -to use. The next section will explain you how you can accomplish just that. - - -[[aws-request-handlers]] -== AWS Request Handlers - -The adapter has a couple of generic request handlers that you can use. The most generic is (and the one we used in the Getting Started section) -is `org.springframework.cloud.function.adapter.aws.FunctionInvoker` which is the implementation of AWS's `RequestStreamHandler`. -User doesn't need to do anything other then specify it as 'handler' on AWS dashboard when deploying function. -It will handle most of the case including Kinesis, streaming etc. . - - -If your app has more than one `@Bean` of type `Function` etc. then you can choose the one to use by configuring `spring.cloud.function.definition` -property or environment variable. The functions are extracted from the Spring Cloud `FunctionCatalog`. In the event you don't specify `spring.cloud.function.definition` -the framework will attempt to find a default following the search order where it searches first for `Function` then `Consumer` and finally `Supplier`). - - -[[aws-function-routing]] -== AWS Function Routing - -One of the core features of Spring Cloud Function is https://docs.spring.io/spring-cloud-function/docs/{project-version}/reference/html/spring-cloud-function.html#_function_routing_and_filtering[routing] -- an ability to have one special function to delegate to other functions based on the user provided routing instructions. - -In AWS Lambda environment this feature provides one additional benefit, as it allows you to bind a single function (Routing Function) -as AWS Lambda and thus a single HTTP endpoint for API Gateway. So in the end you only manage one function and one endpoint, while benefiting -from many function that can be part of your application. - -More details are available in the provided https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-aws-routing[sample], -yet few general things worth mentioning. - -Routing capabilities will be enabled by default whenever there is more then one function in your application as `org.springframework.cloud.function.adapter.aws.FunctionInvoker` -can not determine which function to bind as AWS Lambda, so it defaults to `RoutingFunction`. -This means that all you need to do is provide routing instructions which you can do https://docs.spring.io/spring-cloud-function/docs/{project-version}/reference/html/spring-cloud-function.html#_function_routing_and_filtering[using several mechanisms] -(see https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-aws-routing[sample] for more details). - -Also, note that since AWS does not allow dots `.` and/or hyphens`-` in the name of the environment variable, you can benefit from boot support and simply substitute -dots with underscores and hyphens with camel case. So for example `spring.cloud.function.definition` becomes `spring_cloud_function_definition` -and `spring.cloud.function.routing-expression` becomes `spring_cloud_function_routingExpression`. - -[[aws-function-routing-with-custom-runtime]] -=== AWS Function Routing with Custom Runtime - -When using <> Function Routing works the same way. All you need is to specify `functionRouter` as AWS Handler the same way you would use the name of the function as handler. - -[[notes-on-jar-layout]] -== Notes on JAR Layout - -You don't need the Spring Cloud Function Web or Stream adapter at runtime in Lambda, so you might -need to exclude those before you create the JAR you send to AWS. A Lambda application has to be -shaded, but a Spring Boot standalone application does not, so you can run the same app using 2 -separate jars (as per the sample). The sample app creates 2 jar files, one with an `aws` -classifier for deploying in Lambda, and one [[thin-jar,thin jar]] executable (thin) jar that includes `spring-cloud-function-web` -at runtime. Spring Cloud Function will try and locate a "main class" for you from the JAR file -manifest, using the `Start-Class` attribute (which will be added for you by the Spring Boot -tooling if you use the starter parent). If there is no `Start-Class` in your manifest you can -use an environment variable or system property `MAIN_CLASS` when you deploy the function to AWS. - -If you are not using the functional bean definitions but relying on Spring Boot's auto-configuration, -and are not depending on `spring-boot-starter-parent`, -then additional transformers must be configured as part of the maven-shade-plugin execution. - -[[shade-plugin-setup]] -[source, xml] ----- - - org.apache.maven.plugins - maven-shade-plugin - - - org.springframework.boot - spring-boot-maven-plugin - 2.7.4 - - - - - - shade - - - false - true - aws - - - META-INF/spring.handlers - - - META-INF/spring.factories - - - META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports - - - META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports - - - META-INF/spring.schemas - - - META-INF/spring.components - - - - - - ----- - -[[build-file-setup]] -== Build file setup - -In order to run Spring Cloud Function applications on AWS Lambda, you can leverage Maven or Gradle - plugins offered by the cloud platform provider. - - -[[maven]] -=== Maven - -In order to use the adapter plugin for Maven, add the plugin dependency to your `pom.xml` -file: - -[source,xml] ----- - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - ----- - -As pointed out in the <>, you will need a shaded jar in order to upload it -to AWS Lambda. You can use the https://maven.apache.org/plugins/maven-shade-plugin/[Maven Shade Plugin] for that. -The example of the xref:adapters/aws-intro.adoc#shade-plugin-setup[setup] can be found above. - -You can use the Spring Boot Maven Plugin to generate the <>. -[source,xml] ----- - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - ----- - -You can find the entire sample `pom.xml` file for deploying Spring Cloud Function -applications to AWS Lambda with Maven https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/pom.xml[here]. - -[[gradle]] -=== Gradle - -In order to use the adapter plugin for Gradle, add the dependency to your `build.gradle` file: - -[source,groovy] ----- - -dependencies { - compile("org.springframework.cloud:spring-cloud-function-adapter-aws:${version}") -} ----- - -As pointed out in <>, you will need a shaded jar in order to upload it -to AWS Lambda. You can use the https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow/[Gradle Shadow Plugin] for that: - -[source,groovy] ----- -buildscript { - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:${shadowPluginVersion}" - } -} -apply plugin: 'com.github.johnrengelman.shadow' - -assemble.dependsOn = [shadowJar] - -import com.github.jengelman.gradle.plugins.shadow.transformers.* - -shadowJar { - classifier = 'aws' - dependencies { - exclude( - dependency("org.springframework.cloud:spring-cloud-function-web:${springCloudFunctionVersion}")) - } - // Required for Spring - mergeServiceFiles() - append 'META-INF/spring.handlers' - append 'META-INF/spring.schemas' - append 'META-INF/spring.tooling' - append 'META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports' - append 'META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports' - transform(PropertiesFileTransformer) { - paths = ['META-INF/spring.factories'] - mergeStrategy = "append" - } -} - ----- - -You can use the Spring Boot Gradle Plugin and Spring Boot Thin Gradle Plugin to generate -the <>. - -[source,groovy] ----- -buildscript { - dependencies { - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} -apply plugin: 'org.springframework.boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' -assemble.dependsOn = [thinJar] ----- - -You can find the entire sample `build.gradle` file for deploying Spring Cloud Function -applications to AWS Lambda with Gradle https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-aws/build.gradle[here]. - -[[upload]] -== Upload - -Build the sample under `spring-cloud-function-samples/function-sample-aws` and upload the `-aws` jar file to Lambda. The handler can be `example.Handler` or `org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler` (FQN of the class, _not_ a method reference, although Lambda does accept method references). - ----- -./mvnw -U clean package ----- - -Using the AWS command line tools it looks like this: - ----- -aws lambda create-function --function-name Uppercase --role arn:aws:iam::[USERID]:role/service-role/[ROLE] --zip-file fileb://function-sample-aws/target/function-sample-aws-2.0.0.BUILD-SNAPSHOT-aws.jar --handler org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler --description "Spring Cloud Function Adapter Example" --runtime java8 --region us-east-1 --timeout 30 --memory-size 1024 --publish ----- - -The input type for the function in the AWS sample is a Foo with a single property called "value". So you would need this to test it: - ----- -{ - "value": "test" -} ----- - -NOTE: The AWS sample app is written in the "functional" style (as an `ApplicationContextInitializer`). This is much faster on startup in Lambda than the traditional `@Bean` style, so if you don't need `@Beans` (or `@EnableAutoConfiguration`) it's a good choice. Warm starts are not affected. - - -[[type-conversion]] -== Type Conversion - -Spring Cloud Function will attempt to transparently handle type conversion between the raw -input stream and types declared by your function. - -For example, if your function signature is as such `Function` we will attempt to convert -incoming stream event to an instance of `Foo`. - -In the event type is not known or can not be determined (e.g., `Function`) we will attempt to -convert an incoming stream event to a generic `Map`. - -[[raw-input]] -==== Raw Input - -There are times when you may want to have access to a raw input. In this case all you need is to declare your -function signature to accept `InputStream`. For example, `Function`. In this case -we will not attempt any conversion and will pass the raw input directly to a function. - - - - - diff --git a/docs/modules/ROOT/pages/adapters/aws.adoc b/docs/modules/ROOT/pages/adapters/aws.adoc deleted file mode 100644 index 271179d39..000000000 --- a/docs/modules/ROOT/pages/adapters/aws.adoc +++ /dev/null @@ -1,100 +0,0 @@ -*{project-version}* - - -The https://aws.amazon.com/[AWS] adapter takes a Spring Cloud Function app and converts it to a form that can run in AWS Lambda. - -[[introduction]] -= Introduction - - -[[functional-bean-definitions]] -= Functional Bean Definitions - -Your functions will start much quicker if you can use functional bean definitions instead of `@Bean`. To do this make your main class -an `ApplicationContextInitializer` and use the `registerBean()` methods in `GenericApplicationContext` to -create all the beans you need. You function need to be registered as a bean of type `FunctionRegistration` so that the input and -output types can be accessed by the framework. There is an example in github (the AWS sample is written in this style). It would -look something like this: - -```java -@SpringBootConfiguration -public class FuncApplication implements ApplicationContextInitializer { - - public static void main(String[] args) throws Exception { - FunctionalSpringApplication.run(FuncApplication.class, args); - } - - public Function function() { - return value -> new Bar(value.uppercase())); - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration>(function()) - .type(FunctionTypeUtils.functionType(Foo.class, Bar.class))); - } - -} -``` - -[[aws-context]] -= AWS Context - -In a typical implementation of AWS Handler user has access to AWS _context_ object. With function approach you can have the same experience if you need it. -Upon each invocation the framework will add `aws-context` message header containing the AWS _context_ instance for that particular invocation. So if you need to access it -you can simply have `Message` as an input parameter to your function and then access `aws-context` from message headers. -For convenience we provide AWSLambdaUtils.AWS_CONTEXT constant. - -[[platform-specific-features]] -= Platform Specific Features - -[[http-and-api-gateway]] -== HTTP and API Gateway - -AWS has some platform-specific data types, including batching of messages, which is much more efficient than processing each one individually. To make use of these types you can write a function that depends on those types. Or you can rely on Spring to extract the data from the AWS types and convert it to a Spring `Message`. To do this you tell AWS that the function is of a specific generic handler type (depending on the AWS service) and provide a bean of type `Function,Message>`, where `S` and `T` are your business data types. If there is more than one bean of type `Function` you may also need to configure the Spring Boot property `function.name` to be the name of the target bean (e.g. use `FUNCTION_NAME` as an environment variable). - -The supported AWS services and generic handler types are listed below: - -|=== -| Service | AWS Types | Generic Handler | - -| API Gateway | `APIGatewayProxyRequestEvent`, `APIGatewayProxyResponseEvent` | `org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler` | -| Kinesis | KinesisEvent | org.springframework.cloud.function.adapter.aws.SpringBootKinesisEventHandler | -|=== - - -For example, to deploy behind an API Gateway, use `--handler org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler` in your AWS command line (in via the UI) and define a `@Bean` of type `Function,Message>` where `Foo` and `Bar` are POJO types (the data will be marshalled and unmarshalled by AWS using Jackson). - -[[custom-runtime]] -= Custom Runtime - -You can also benefit from https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html[AWS Lambda custom runtime] feature of AWS Lambda -and Spring Cloud Function provides all the necessary components to make it easy. - -From the code perspective the application should look no different then any other Spring Cloud Function application. -The only thing you need to do is to provide a `bootstrap` script in the root of your zip/jar that runs the Spring Boot application. -and select "Custom Runtime" when creating a function in AWS. -Here is an example 'bootstrap' file: -```text -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -java -Dspring.main.web-application-type=none -Dspring.jmx.enabled=false \ - -noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \ - -Djava.security.egd=file:/dev/./urandom \ - -cp .:`echo lib/*.jar | tr ' ' :` com.example.LambdaApplication -``` -The `com.example.LambdaApplication` represents your application which contains function beans. - -Set the handler name in AWS to the name of your function. You can use function composition here as well (e.g., `uppecrase|reverse`). -That is pretty much all. Once you upload your zip/jar to AWS your function will run in custom runtime. -We provide a https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-aws-custom-new[sample project] -where you can also see how to configure yoru POM to properly generate the zip file. - -The functional bean definition style works for custom runtimes as well, and is -faster than the `@Bean` style. A custom runtime can start up much quicker even than a functional bean implementation -of a Java lambda - it depends mostly on the number of classes you need to load at runtime. -Spring doesn't do very much here, so you can reduce the cold start time by only using primitive types in your function, for instance, -and not doing any work in custom `@PostConstruct` initializers. diff --git a/docs/modules/ROOT/pages/adapters/azure-intro.adoc b/docs/modules/ROOT/pages/adapters/azure-intro.adoc deleted file mode 100644 index 2a6394961..000000000 --- a/docs/modules/ROOT/pages/adapters/azure-intro.adoc +++ /dev/null @@ -1,548 +0,0 @@ -:branch: master - -[[microsoft-azure-functions]] -= Microsoft Azure Functions -:sectnums: - -https://azure.microsoft.com[Azure] function adapter for deploying `Spring Cloud Function` applications as native Azure Java Functions. - -The `Azure Functions` https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java[programming model] relays, extensively, on Java https://learn.microsoft.com/en-us/java/api/com.microsoft.azure.functions.annotation?view=azure-java-stable[annotations] for defining the function's handler methods and their input and output types. -At compile time the annotated classes are processed by the provided Azure Maven/Gradle plugins to generate the necessary Azure Function binding files, configurations and package artifacts. -The Azure annotations are just a type-safe way to configure your java function to be recognized as Azure function. - -The https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[spring-cloud-function-adapter-azure] extends the basic programming model to provide Spring and Spring Cloud Function support. -With the adapter you can build your Spring Cloud Function application using dependency injections and then auto-wire the necessary services into your Azure handler methods. - -image::../images/scf-azure-adapter.svg[width=800,scaledwidth="75%",align="center"] - -TIP: For Web-based function applications, you can replace the generic `adapter-azure` with the specialized https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web[spring-cloud-function-adapter-azure-web]. -With the Azure Web Adapter you can deploy any Spring Web application as an Azure, HttpTrigger, function. -This adapter hides the Azure annotations complexity and uses the familiar https://docs.spring.io/spring-boot/docs/current/reference/html/web.html[Spring Web] programming model instead. -For further information follow the xref:adapters/azure-intro.adoc#azure.web.adapter[Azure Web Adapter] section below. - -[[azure-adapter]] -= Azure Adapter - -Provides `Spring` & `Spring Cloud Function` integration for Azure Functions. - -[[dependencies]] -== Dependencies - -In order to enable the Azure Function integration add the azure adapter dependency to your `pom.xml` or `build.gradle` -files: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - - org.springframework.cloud - spring-cloud-function-adapter-azure - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -dependencies { - implementation 'org.springframework.cloud:spring-cloud-function-adapter-azure' -} ----- -==== - -NOTE: version `4.0.0+` is required. Having the adapter on the classpath activates the Azure Java Worker integration. - -[[azure.development.guidelines]] -== Development Guidelines - -Use the `@Component` (or `@Service`) annotation to turn any exiting Azure Function class (e.g. with `@FunctionName` handlers) into a Spring component. -Then you can auto-wire the required dependencies (or the xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] for Spring Cloud Function composition) and use those inside the Azure function handlers. - -[source,java] ----- -@Component // <1> -public class MyAzureFunction { - - // Plain Spring bean - not a Spring Cloud Functions! - @Autowired private Function uppercase; // <2> - - // The FunctionCatalog leverages the Spring Cloud Function framework. - @Autowired private FunctionCatalog functionCatalog; // <2> - - @FunctionName("spring") // <3> - public String plainBean( // <4> - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - return this.uppercase.apply(request.getBody().get()); - } - - @FunctionName("scf") // <3> - public String springCloudFunction( // <5> - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - // Use SCF composition. Composed functions are not just spring beans but SCF such. - Function composed = this.functionCatalog.lookup("reverse|uppercase"); // <6> - - return (String) composed.apply(request.getBody().get()); - } -} ----- - -<1> Indicates that the `MyAzureFunction` class is a "component" to be considered by the Spring Framework as a candidate for auto-detection and classpath scanning. -<2> Auto-wire the `uppercase` and `functionCatalog` beans defined in the `HttpTriggerDemoApplication` (below). -<3> The https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#java-function-basics[@FunctionName] annotation identifies the designated Azure function handlers. -When invoked by a trigger (such as `@HttpTrigger`), functions process that trigger, and any other inputs, to produce one or more outputs. -<4> The `plainBean` method handler is mapped to an Azure function that uses of the auto-wired `uppercase` spring bean to compute the result. -It demonstrates how to use "plain" Spring components in your Azure handlers. -<5> The `springCloudFunction` method handler is mapped to another Azure function, that uses the auto-wired `FunctionCatalog` instance to compute the result. -<6> Shows how to leverage the Spring Cloud Function xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] composition API. - -TIP: Use the Java annotations included in the https://learn.microsoft.com/en-us/java/api/com.microsoft.azure.functions.annotation?view=azure-java-stable[com.microsoft.azure.functions.annotation.*] package to bind input and outputs to your methods. - -The implementation of the business logic used inside the Azure handlers looks like a common Spring application: - -[[HttpTriggerDemoApplication]] - -[source,java] ----- -@SpringBootApplication // <1> -public class HttpTriggerDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(HttpTriggerDemoApplication.class, args); - } - - @Bean - public Function uppercase() { // <2> - return payload -> payload.toUpperCase(); - } - - @Bean - public Function reverse() { // <2> - return payload -> new StringBuilder(payload).reverse().toString(); - } -} ----- -<1> The `@SpringBootApplication` annotated class is used as a `Main-Class` as explained in xref:adapters/azure-intro.adoc#star-class-configuration[main class configuration]. -<2> Functions auto-wired and used in the Azure function handlers. - -[[function-catalog]] -=== Function Catalog - -The Spring Cloud Function supports a range of type signatures for user-defined functions, while providing a consistent execution model. -For this it uses the xref:spring-cloud-function/programming-model.adoc#function.catalog[Function Catalog] to transform all user defined functions into a canonical representation. - -The Azure adapter can auto-wire any Spring component, such as the `uppercase` above. -But those are treated as plain Java class instances, not as a canonical Spring Cloud Functions! - -To leverage Spring Cloud Function and have access to the canonical function representations, you need to auto-wire the `FunctionCatalog` and use it in your handler, like the `functionCatalog` instance the `springCloudFunction()` handler above. - -[[accessing-azure-executioncontext]] -=== Accessing Azure ExecutionContext - -Some time there is a need to access the target execution context provided by the Azure runtime in the form of `com.microsoft.azure.functions.ExecutionContext`. -For example one of such needs is logging, so it can appear in the Azure console. - -For that purpose the `AzureFunctionUtil.enhanceInputIfNecessary` allow you to add an instance of the `ExecutionContext` as a Message header so you can retrieve it via `executionContext` key. - -[source,java] ----- -@FunctionName("myfunction") -public String execute( - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - Message message = - (Message) AzureFunctionUtil.enhanceInputIfNecessary(request.getBody().get(), context); // <1> - - return this.uppercase.apply(message); -} ----- -<1> Leverages the `AzureFunctionUtil` utility to inline the `context` as message header using the `AzureFunctionUtil.EXECUTION_CONTEXT` header key. - -Now you can retrieve the ExecutionContext from message headers: - -[source,java] ----- -@Bean -public Function, String> uppercase(JsonMapper mapper) { - return message -> { - String value = message.getPayload(); - ExecutionContext context = - (ExecutionContext) message.getHeaders().get(AzureFunctionUtil.EXECUTION_CONTEXT); // <1> - . . . - } -} ----- -<1> Retrieve the ExecutionContext instance from the header. - - -[[azure.configuration]] -== Configuration - -To run your function applications on Microsoft Azure, you have to provide the necessary configurations, such as `function.json` and `host.json`, and adhere to the compulsory https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#folder-structure[packaging format]. - -Usually the Azure Maven (or Gradle) plugins are used to generate the necessary configurations from the annotated classes and to produce the required package format. - -IMPORTANT: The Azure https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#folder-structure[packaging format] is not compatible with the default Spring Boot packaging (e.g. `uber jar`). -The xref:adapters/azure-intro.adoc#disable.spring.boot.plugin[Disable Spring Boot Plugin] section below explains how to handle this. - -[[azure-maven/gradle-plugins]] -=== Azure Maven/Gradle Plugins - -Azure provides https://github.com/microsoft/azure-maven-plugins/tree/develop/azure-functions-maven-plugin[Maven] and https://github.com/microsoft/azure-gradle-plugins/tree/master/azure-functions-gradle-plugin[Gradle] plugins to process the annotated classes, generate the necessary configurations and produce the expected package layout. -Plugins are used to set the platform, runtime and app-settings properties like this: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - com.microsoft.azure - azure-functions-maven-plugin - 1.22.0 or higher - - - YOUR-AZURE-FUNCTION-APP-NAME - YOUR-AZURE-FUNCTION-RESOURCE-GROUP - YOUR-AZURE-FUNCTION-APP-REGION - YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME - YOUR-AZURE-FUNCTION-PRICING-TIER - - ${project.basedir}/src/main/resources/host.json - - - linux - 11 - - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -plugins { - id "com.microsoft.azure.azurefunctions" version "1.11.0" - // ... -} - -apply plugin: "com.microsoft.azure.azurefunctions" - -azurefunctions { - appName = 'YOUR-AZURE-FUNCTION-APP-NAME' - resourceGroup = 'YOUR-AZURE-FUNCTION-RESOURCE-GROUP' - region = 'YOUR-AZURE-FUNCTION-APP-REGION' - appServicePlanName = 'YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME' - pricingTier = 'YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME' - - runtime { - os = 'linux' - javaVersion = '11' - } - - auth { - type = 'azure_cli' - } - - appSettings { - FUNCTIONS_EXTENSION_VERSION = '~4' - } - // Uncomment to enable local debug - // localDebug = "transport=dt_socket,server=y,suspend=n,address=5005" -} ----- -==== - -More information about the runtime configurations: https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#java-versions[Java Versions], https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#specify-the-deployment-os[Deployment OS]. - -[[disable.spring.boot.plugin]] -=== Disable Spring Boot Plugin - -Expectedly, the Azure Functions run inside the Azure execution runtime, not inside the SpringBoot runtime! -Furthermore, Azure expects a specific packaging format, generated by the Azure Maven/Gradle plugins, that is not compatible with the default Spring Boot packaging. - -You have to either disable the SpringBoot Maven/Gradle plugin or use the https://github.com/dsyer/spring-boot-thin-launcher[Spring Boot Thin Launcher] as shown in this Maven snippet: - -[source,xml] ----- - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - - - ----- - -[[star-class-configuration]] -=== Main-Class Configuration - -Specify the `Main-Class`/`Start-Class` to point to your Spring application entry point, such as the xref:adapters/azure-intro.adoc#HttpTriggerDemoApplication[HttpTriggerDemoApplication] class in the example above. - -You can use the Maven `start-class` property or set the `Main-Class` attribute of your `MANIFEST/META-INFO`: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - YOUR APP MAIN CLASS - ... - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -jar { - manifest { - attributes( - "Main-Class": "YOUR-APP-MAIN-CLASS" - ) - } -} ----- -==== - -TIP: Alternatively you can use the `MAIN_CLASS` environment variable to set the class name explicitly. -For local runs, add the `MAIN_CLASS` variable to your `local.settings.json` file and for Azure portal deployment set the variable in the https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#get-started-in-the-azure-portal[App Settings]. - - -IMPORTANT: If the `MAIN_CLASS` variable is not set, the Azure adapter lookups the `MANIFEST/META-INFO` attributes from the jars found on the classpath and selects the first `Main-Class:` annotated with either a `@SpringBootApplication` or `@SpringBootConfiguration` annotation. - -[[metadata-configuration]] -=== Metadata Configuration - -You can use a shared https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json[host.json] file to configure the function app. - -[source,json] ----- -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[4.*, 5.0.0)" - } -} ----- - -The host.json metadata file contains configuration options that affect all functions in a function app instance. - -TIP: If the file is not in the project top folder you need to configure your plugins accordingly (like `hostJson` maven attribute). - -[[samples]] -== Samples - -Here is a list of various Spring Cloud Function Azure Adapter samples you can explore: - -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-http-trigger[Http Trigger (Maven)] -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle[Http Trigger (Gradle)] -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-blob-trigger[Blob Trigger (Maven)] -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-timer-trigger[Timer Trigger (Maven)] -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-kafka-trigger[ Kafka Trigger & Output Binding (Maven)]. - -[[azure.web.adapter]] -= Azure Web Adapter - -For, pure, Web-based function applications, you can replace the generic `adapter-azure` with the specialized https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web[spring-cloud-function-adapter-azure-web]. -The Azure Web Adapter can deploy any Spring Web application as a native Azure function, using the HttpTrigger internally. -It hides the Azure annotations complexity and relies on the familiar https://docs.spring.io/spring-boot/docs/current/reference/html/web.html[Spring Web] programming model instead. - -To enable the Azure Web Adapter, add the adapter dependency to your `pom.xml` or `build.gradle` files: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - - org.springframework.cloud - spring-cloud-function-adapter-azure-web - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -dependencies { - implementation 'org.springframework.cloud:spring-cloud-function-adapter-azure-web' -} ----- -==== - -The same xref:adapters/azure-intro.adoc#azure.configuration[Configuration] and xref:adapters/azure-intro.adoc#azure.usage[Usage] instructions apply to the `Azure Web Adapter` as well. - - -[[samples]] -== Samples - -For further information, explore the following, Azure Web Adapter, sample: - -- https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-web[ Azure Web Adapter (Maven)]. - -[[azure.usage]] -= Usage - -Common instructions for building and deploying both, `Azure Adapter` and `Azure Web Adapter` type of applications. - -[[build]] -== Build - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -./mvnw -U clean package ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -./gradlew azureFunctionsPackage ----- -==== - -[[running-locally]] -== Running locally - -To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here]). -For some configuration you would need the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator[Azurite emulator] as well. - -Then run the sample: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -./mvnw azure-functions:run ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -./gradlew azureFunctionsRun ----- -==== - -[[running-on-azure]] -== Running on Azure - -Make sure you are logged in your Azure account. - ----- -az login ----- - -and deploy - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -./mvnw azure-functions:deploy ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -./gradlew azureFunctionsDeploy ----- -==== - -[[debug-locally]] -== Debug locally - -Run the function in debug mode. - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -./mvnw azure-functions:run -DenableDebug ----- -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle - ----- -// If you want to debug your functions, please add the following line -// to the azurefunctions section of your build.gradle. -azurefunctions { - ... - localDebug = "transport=dt_socket,server=y,suspend=n,address=5005" -} ----- -==== - -Alternatively and the `JAVA_OPTS` value to your `local.settings.json` like this: - -[source,json] ----- -{ - "IsEncrypted": false, - "Values": { - ... - "FUNCTIONS_WORKER_RUNTIME": "java", - "JAVA_OPTS": "-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005" - } -} ----- - -Here is snippet for a `VSCode` remote debugging configuration: - -[source,json] ----- -{ - "version": "0.2.0", - "configurations": [ - { - "type": "java", - "name": "Attach to Remote Program", - "request": "attach", - "hostName": "localhost", - "port": "5005" - }, - ] -} ----- - -[[functioninvoker-deprecated]] -= FunctionInvoker (deprecated) - -WARNING: The legacy `FunctionInvoker` programming model is deprecated and will not be supported going forward. - -For additional documentation and samples about the Function Integration approach follow the https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure/[azure-sample] README and code. - -[[relevant-links]] -= Relevant Links - -- https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/getting-started-with-spring-cloud-function-in-azure[Spring Cloud Function in Azure] -- https://spring.io/blog/2023/02/24/spring-cloud-function-for-azure-function[Spring Cloud Function for Azure Function (blog)] -- <> -- https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption[Azure Functions Java developer guide] -- https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference?tabs=blob[Azure Functions developer guide] - -:sectnums!: diff --git a/docs/modules/ROOT/pages/adapters/azure.adoc b/docs/modules/ROOT/pages/adapters/azure.adoc deleted file mode 100644 index 490093572..000000000 --- a/docs/modules/ROOT/pages/adapters/azure.adoc +++ /dev/null @@ -1,2 +0,0 @@ -*{project-version}* - diff --git a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc b/docs/modules/ROOT/pages/adapters/gcp-intro.adoc deleted file mode 100644 index af9d79821..000000000 --- a/docs/modules/ROOT/pages/adapters/gcp-intro.adoc +++ /dev/null @@ -1,304 +0,0 @@ -:branch: master - -[[google-cloud-functions]] -= Google Cloud Functions - -The Google Cloud Functions adapter enables Spring Cloud Function apps to run on the https://cloud.google.com/functions[Google Cloud Functions] serverless platform. -You can either run the function locally using the open source https://github.com/GoogleCloudPlatform/functions-framework-java[Google Functions Framework for Java] or on GCP. - -[[project-dependencies]] -== Project Dependencies - -Start by adding the `spring-cloud-function-adapter-gcp` dependency to your project. - -[source, xml] ----- - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - - - ... - ----- - -In addition, add the `spring-boot-maven-plugin` which will build the JAR of the function to deploy. - -NOTE: Notice that we also reference `spring-cloud-function-adapter-gcp` as a dependency of the `spring-boot-maven-plugin`. This is necessary because it modifies the plugin to package your function in the correct JAR format for deployment on Google Cloud Functions. - -[source, xml] ----- - - org.springframework.boot - spring-boot-maven-plugin - - target/deploy - - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - - - ----- - -Finally, add the Maven plugin provided as part of the Google Functions Framework for Java. -This allows you to test your functions locally via `mvn function:run`. - -NOTE: The function target should always be set to `org.springframework.cloud.function.adapter.gcp.GcfJarLauncher`; this is an adapter class which acts as the entry point to your Spring Cloud Function from the Google Cloud Functions platform. - -[source,xml] ----- - - com.google.cloud.functions - function-maven-plugin - 0.9.1 - - org.springframework.cloud.function.adapter.gcp.GcfJarLauncher - 8080 - - ----- - -A full example of a working `pom.xml` can be found in the https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-gcp-http/pom.xml[Spring Cloud Functions GCP sample]. - -[[http-functions]] -== HTTP Functions - -Google Cloud Functions supports deploying https://cloud.google.com/functions/docs/writing/http[HTTP Functions], which are functions that are invoked by HTTP request. The sections below describe instructions for deploying a Spring Cloud Function as an HTTP Function. - -[[getting-started]] -=== Getting Started - -Let’s start with a simple Spring Cloud Function example: - -[source, java] ----- -@SpringBootApplication -public class CloudFunctionMain { - - public static void main(String[] args) { - SpringApplication.run(CloudFunctionMain.class, args); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } -} ----- - -Specify your configuration main class in `resources/META-INF/MANIFEST.MF`. - -[source] ----- -Main-Class: com.example.CloudFunctionMain ----- - -Then run the function locally. -This is provided by the Google Cloud Functions `function-maven-plugin` described in the project dependencies section. - ----- -mvn function:run ----- - -Invoke the HTTP function: - ----- -curl http://localhost:8080/ -d "hello" ----- - -[[deploy-to-gcp]] -=== Deploy to GCP - -Start by packaging your application. - ----- -mvn package ----- - -If you added the custom `spring-boot-maven-plugin` plugin defined above, you should see the resulting JAR in `target/deploy` directory. -This JAR is correctly formatted for deployment to Google Cloud Functions. - -Next, make sure that you have the https://cloud.google.com/sdk/install[Cloud SDK CLI] installed. - -From the project base directory run the following command to deploy. - ----- -gcloud functions deploy function-sample-gcp-http \ ---entry-point org.springframework.cloud.function.adapter.gcp.GcfJarLauncher \ ---runtime java11 \ ---trigger-http \ ---source target/deploy \ ---memory 512MB ----- - -Invoke the HTTP function: - ----- -curl https://REGION-PROJECT_ID.cloudfunctions.net/function-sample-gcp-http -d "hello" ----- - - -Setting custom HTTP statusCode: - ----- -Functions can specify a custom HTTP response code by setting the `FunctionInvoker.HTTP_STATUS_CODE` header. ----- - -[source, java] ----- -@Bean -public Function> function() { - - String payload = "hello"; - - Message message = MessageBuilder.withPayload(payload).setHeader(FunctionInvoker.HTTP_STATUS_CODE, 404).build(); - - return input -> message; -}; ----- - - - -[[background-functions]] -== Background Functions - -Google Cloud Functions also supports deploying https://cloud.google.com/functions/docs/writing/background[Background Functions] which are invoked indirectly in response to an event, such as a message on a https://cloud.google.com/pubsub[Cloud Pub/Sub] topic, a change in a https://cloud.google.com/storage[Cloud Storage] bucket, or a https://firebase.google.com/[Firebase] event. - -The `spring-cloud-function-adapter-gcp` allows for functions to be deployed as background functions as well. - -The sections below describe the process for writing a Cloud Pub/Sub topic background function. -However, there are a number of different event types that can trigger a background function to execute which are not discussed here; these are described in the https://cloud.google.com/functions/docs/calling[Background Function triggers documentation]. - -[[getting-started]] -=== Getting Started - -Let’s start with a simple Spring Cloud Function which will run as a GCF background function: - -[source, java] ----- -@SpringBootApplication -public class BackgroundFunctionMain { - - public static void main(String[] args) { - SpringApplication.run(BackgroundFunctionMain.class, args); - } - - @Bean - public Consumer pubSubFunction() { - return message -> System.out.println("The Pub/Sub message data: " + message.getData()); - } -} ----- - -In addition, create `PubSubMessage` class in the project with the below definition. -This class represents the https://cloud.google.com/functions/docs/calling/pubsub#event_structure[Pub/Sub event structure] which gets passed to your function on a Pub/Sub topic event. - -[source, java] ----- -public class PubSubMessage { - - private String data; - - private Map attributes; - - private String messageId; - - private String publishTime; - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public String getMessageId() { - return messageId; - } - - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - public String getPublishTime() { - return publishTime; - } - - public void setPublishTime(String publishTime) { - this.publishTime = publishTime; - } - -} ----- - -Specify your configuration main class in `resources/META-INF/MANIFEST.MF`. - -[source] ----- -Main-Class: com.example.BackgroundFunctionMain ----- - -Then run the function locally. -This is provided by the Google Cloud Functions `function-maven-plugin` described in the project dependencies section. - ----- -mvn function:run ----- - -Invoke the HTTP function: - ----- -curl localhost:8080 -H "Content-Type: application/json" -d '{"data":"hello"}' ----- - -Verify that the function was invoked by viewing the logs. - -[[deploy-to-gcp]] -=== Deploy to GCP - -In order to deploy your background function to GCP, first package your application. - ----- -mvn package ----- - -If you added the custom `spring-boot-maven-plugin` plugin defined above, you should see the resulting JAR in `target/deploy` directory. -This JAR is correctly formatted for deployment to Google Cloud Functions. - -Next, make sure that you have the https://cloud.google.com/sdk/install[Cloud SDK CLI] installed. - -From the project base directory run the following command to deploy. - ----- -gcloud functions deploy function-sample-gcp-background \ ---entry-point org.springframework.cloud.function.adapter.gcp.GcfJarLauncher \ ---runtime java11 \ ---trigger-topic my-functions-topic \ ---source target/deploy \ ---memory 512MB ----- - -Google Cloud Function will now invoke the function every time a message is published to the topic specified by `--trigger-topic`. - -For a walkthrough on testing and verifying your background function, see the instructions for running the https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-background/[GCF Background Function sample]. - -[[sample-functions]] -== Sample Functions - -The project provides the following sample functions as reference: - -* The https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-http/[function-sample-gcp-http] is an HTTP Function which you can test locally and try deploying. -* The https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-background/[function-sample-gcp-background] shows an example of a background function that is triggered by a message being published to a specified Pub/Sub topic. diff --git a/docs/modules/ROOT/pages/adapters/gcp.adoc b/docs/modules/ROOT/pages/adapters/gcp.adoc deleted file mode 100644 index 490093572..000000000 --- a/docs/modules/ROOT/pages/adapters/gcp.adoc +++ /dev/null @@ -1,2 +0,0 @@ -*{project-version}* - diff --git a/docs/modules/ROOT/pages/functional.adoc b/docs/modules/ROOT/pages/functional.adoc deleted file mode 100644 index 68958a89c..000000000 --- a/docs/modules/ROOT/pages/functional.adoc +++ /dev/null @@ -1,321 +0,0 @@ -Spring Cloud Function supports a "functional" style of bean declarations for small apps where you need fast startup. The functional style of bean declaration was a feature of Spring Framework 5.0 with significant enhancements in 5.1. - -[[comparing-functional-with-traditional-bean-definitions]] -= Comparing Functional with Traditional Bean Definitions - -Here's a vanilla Spring Cloud Function application from with the -familiar `@Configuration` and `@Bean` declaration style: - -```java -@SpringBootApplication -public class DemoApplication { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - public static void main(String[] args) { - SpringApplication.run(DemoApplication.class, args); - } - -} -``` - -Now for the functional beans: the user application code can be recast into "functional" -form, like this: - -```java -@SpringBootConfiguration -public class DemoApplication implements ApplicationContextInitializer { - - public static void main(String[] args) { - FunctionalSpringApplication.run(DemoApplication.class, args); - } - - public Function uppercase() { - return value -> value.toUpperCase(); - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("demo", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()) - .type(FunctionTypeUtils.functionType(String.class, String.class))); - } - -} -``` - -The main differences are: - -* The main class is an `ApplicationContextInitializer`. - -* The `@Bean` methods have been converted to calls to `context.registerBean()` - -* The `@SpringBootApplication` has been replaced with -`@SpringBootConfiguration` to signify that we are not enabling Spring -Boot autoconfiguration, and yet still marking the class as an "entry -point". - -* The `SpringApplication` from Spring Boot has been replaced with a -`FunctionalSpringApplication` from Spring Cloud Function (it's a -subclass). - -The business logic beans that you register in a Spring Cloud Function app are of type `FunctionRegistration`. -This is a wrapper that contains both the function and information about the input and output types. In the `@Bean` -form of the application that information can be derived reflectively, but in a functional bean registration some of -it is lost unless we use a `FunctionRegistration`. - -An alternative to using an `ApplicationContextInitializer` and `FunctionRegistration` is to make the application -itself implement `Function` (or `Consumer` or `Supplier`). Example (equivalent to the above): - -```java -@SpringBootConfiguration -public class DemoApplication implements Function { - - public static void main(String[] args) { - FunctionalSpringApplication.run(DemoApplication.class, args); - } - - @Override - public String apply(String value) { - return value.toUpperCase(); - } - -} -``` - -It would also work if you add a separate, standalone class of type `Function` and register it with -the `SpringApplication` using an alternative form of the `run()` method. The main thing is that the generic -type information is available at runtime through the class declaration. - -Suppose you have -[source, java] ----- -@Component -public class CustomFunction implements Function, Flux> { - @Override - public Flux apply(Flux flux) { - return flux.map(foo -> new Bar("This is a Bar object from Foo value: " + foo.getValue())); - } - -} ----- - -You register it as such: - -[source, java] ----- -@Override -public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(new CustomFunction()).type(CustomFunction.class)); -} ----- - -[[limitations-of-functional-bean-declaration]] -= Limitations of Functional Bean Declaration - -Most Spring Cloud Function apps have a relatively small scope compared to the whole of Spring Boot, -so we are able to adapt it to these functional bean definitions easily. If you step outside that limited scope, -you can extend your Spring Cloud Function app by switching back to `@Bean` style configuration, or by using a hybrid -approach. If you want to take advantage of Spring Boot autoconfiguration for integrations with external datastores, -for example, you will need to use `@EnableAutoConfiguration`. Your functions can still be defined using the functional -declarations if you want (i.e. the "hybrid" style), but in that case you will need to explicitly switch off the "full -functional mode" using `spring.functional.enabled=false` so that Spring Boot can take back control. - -[[function_visualization]] -= Function visualization and control - -Spring Cloud Function supports visualization of functions available in `FunctionCatalog` through Actuator endpoints as well as programmatic way. - -[[programmatic-way]] -=== Programmatic way - -To see function available within your application context programmatically all you need is access to `FunctionCatalog`. There you can -finds methods to get the size of the catalog, lookup functions as well as list the names of all the available functions. - -For example, - -[source,java] ----- -FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); -int size = functionCatalog.size(); // will tell you how many functions available in catalog -Set names = functionCatalog.getNames(null); will list the names of all the Function, Suppliers and Consumers available in catalog -. . . ----- - -[[actuator]] -=== Actuator -Since actuator and web are optional, you must first add one of the web dependencies as well as add the actuator dependency manually. -The following example shows how to add the dependency for the Web framework: - -[source,xml] ----- - - org.springframework.boot - spring-boot-starter-web - ----- - -The following example shows how to add the dependency for the WebFlux framework: - -[source,xml] ----- - - org.springframework.boot - spring-boot-starter-webflux - ----- - -You can add the Actuator dependency as follows: -[source,xml] ----- - - org.springframework.boot - spring-boot-starter-actuator - ----- - -You must also enable the `functions` actuator endpoints by setting the following property: `--management.endpoints.web.exposure.include=functions`. - -Access the following URL to see the functions in FunctionCatalog: -`http://:/actuator/functions` - -For example, -[source,text] ----- -curl http://localhost:8080/actuator/functions ----- - -Your output should look something like this: -[source,text] ----- -{"charCounter": - {"type":"FUNCTION","input-type":"string","output-type":"integer"}, - "logger": - {"type":"CONSUMER","input-type":"string"}, - "functionRouter": - {"type":"FUNCTION","input-type":"object","output-type":"object"}, - "words": - {"type":"SUPPLIER","output-type":"string"}. . . ----- - -[[testing-functional-applications]] -= Testing Functional Applications - -Spring Cloud Function also has some utilities for integration testing that will be very familiar to Spring Boot users. - -Suppose this is your application: - -[source, java] ----- -@SpringBootApplication -public class SampleFunctionApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleFunctionApplication.class, args); - } - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } -} ----- - -Here is an integration test for the HTTP server wrapping this application: - -[source, java] ----- -@SpringBootTest(classes = SampleFunctionApplication.class, - webEnvironment = WebEnvironment.RANDOM_PORT) -public class WebFunctionTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void test() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/uppercase")).body("hello"), String.class); - System.out.println(result.getBody()); - } -} ----- - -or when function bean definition style is used: - -[source, java] ----- -@FunctionalSpringBootTest -public class WebFunctionTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void test() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/uppercase")).body("hello"), String.class); - System.out.println(result.getBody()); - } -} ----- - -This test is almost identical to the one you would write for the `@Bean` version of the same app - the only difference -is the `@FunctionalSpringBootTest` annotation, instead of the regular `@SpringBootTest`. All the other pieces, -like the `@Autowired` `TestRestTemplate`, are standard Spring Boot features. - -And to help with correct dependencies here is the excerpt from POM - -[source, xml, subs=attributes+] ----- - - org.springframework.boot - spring-boot-starter-parent - {spring-boot-version} - - - . . . . - - org.springframework.cloud - spring-cloud-function-web - {project-version} - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-web - test - - - org.springframework.boot - spring-boot-starter-test - test - ----- - -Or you could write a test for a non-HTTP app using just the `FunctionCatalog`. For example: - -[source, java] ----- -@FunctionalSpringBootTest -public class FunctionalTests { - - @Autowired - private FunctionCatalog catalog; - - @Test - public void words() { - Function function = catalog.lookup(Function.class, - "uppercase"); - assertThat(function.apply("hello")).isEqualTo("HELLO"); - } - -} ----- diff --git a/docs/modules/ROOT/pages/getting-started.adoc b/docs/modules/ROOT/pages/getting-started.adoc deleted file mode 100644 index f46cbe0c7..000000000 --- a/docs/modules/ROOT/pages/getting-started.adoc +++ /dev/null @@ -1,33 +0,0 @@ -Build from the command line (and "install" the samples): - ----- -$ ./mvnw clean install ----- - -(If you like to YOLO add `-DskipTests`.) - -Run one of the samples, e.g. - ----- -$ java -jar spring-cloud-function-samples/function-sample/target/*.jar ----- - -This runs the app and exposes its functions over HTTP, so you can -convert a string to uppercase, like this: - ----- -$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello -HELLO ----- - -You can convert multiple strings (a `Flux`) by separating them -with new lines - ----- -$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello -> World' -HELLOWORLD ----- - -(You can use `^Q^J` in a terminal to insert a new line in a literal -string like that.) diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc deleted file mode 100644 index 0594f9c27..000000000 --- a/docs/modules/ROOT/pages/index.adoc +++ /dev/null @@ -1,25 +0,0 @@ -[[spring-cloud-function-reference-documentation]] -= Spring Cloud Function Reference Documentation -:page-section-summary-toc: 1 -Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin, Chris Bono, Artem Bilan - -*{project-version}* - -:docinfo: shared - -The reference documentation consists of the following sections: - -[horizontal] -<> :: Spring Cloud Function Reference -https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-cloudevent[Cloud Events] :: Cloud Events -https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-rsocket[RSocket] :: RSocket -xref:spring-integration.adoc[Spring Integration] :: Spring Integration Framework Interaction -<> :: AWS Adapter Reference -<> :: Azure Adapter Reference -<> :: GCP Adapter Reference - - -Relevant Links: - -[horizontal] -https://projectreactor.io/[Reactor] :: Project Reactor diff --git a/docs/modules/ROOT/pages/sagan-index.adoc b/docs/modules/ROOT/pages/sagan-index.adoc deleted file mode 100644 index fac997ff1..000000000 --- a/docs/modules/ROOT/pages/sagan-index.adoc +++ /dev/null @@ -1,46 +0,0 @@ -Spring Cloud Function is a project with the following high-level goals: - -* Promote the implementation of business logic via functions. -* Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task. -* Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS). -* Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers. - -It abstracts away all of the transport details and infrastructure, allowing the developer to keep all the familiar tools and processes, and focus firmly on business logic. - -## Features - -Spring Cloud Function features: - -* _Choice of programming styles - reactive, imperative or hybrid._ -* _Function composition and adaptation (e.g., composing imperative functions with reactive)._ -* _Support for reactive function with multiple inputs and outputs allowing merging, joining and other complex streaming operation to be handled by functions._ -* _Transparent type conversion of inputs and outputs._ -* _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ -* _Adapters to expose function to the outside world as HTTP endpoints etc._ -* _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Microsoft Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], and possibly other "serverless" service providers._ - -Here's a complete, executable, testable Spring Boot application (implementing a simple string manipulation): - -```java -@SpringBootApplication -public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - - @Bean - public Function, Flux> uppercase() { - return flux -> flux.map(value -> value.toUpperCase()); - } -} -``` -### Sample Projects - -* https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample[Vanilla] -* https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-pof[Plain Old Function] -* https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-aws[AWS Lambda] -* https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-azure[Microsoft Azure] -* https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-gcp-http[Google Cloud Functions] - - diff --git a/docs/modules/ROOT/pages/spring-cloud-function.adoc b/docs/modules/ROOT/pages/spring-cloud-function.adoc deleted file mode 100644 index 83270d240..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[spring-cloud-function]] -= Spring Cloud Function -:page-section-summary-toc: 1 - -Mark Fisher, Dave Syer, Oleg Zhurakousky, Anshul Mehra, Dan Dobrin - -*{project-version}* - ---- - -:github: https://github.com/spring-cloud/spring-cloud-function -:githubmaster: {github}/tree/master -:docslink: {githubmaster}/docs/src/main/asciidoc -:nofooter: -:branch: master - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc b/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc deleted file mode 100644 index a3b6ce4a1..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/deploying-a-packaged.adoc +++ /dev/null @@ -1,183 +0,0 @@ -[[deploying-a-packaged-function]] -= Deploying a Packaged Function - -Spring Cloud Function provides a "deployer" library that allows you to launch a jar file (or exploded archive, or set of jar files) with an isolated class loader and expose the functions defined in it. This is quite a powerful tool that would allow you to, for instance, adapt a function to a range of different input-output adapters without changing the target jar file. Serverless platforms often have this kind of feature built in, so you could see it as a building block for a function invoker in such a platform (indeed the https://projectriff.io[Riff] Java function invoker uses this library). - -The standard entry point is to add `spring-cloud-function-deployer` to the classpath, the deployer kicks in and looks for some configuration to tell it where to find the function jar. - -```xml - - org.springframework.cloud - spring-cloud-function-deployer - ${spring.cloud.function.version} - -``` - - -At a minimum the user has to provide a `spring.cloud.function.location` which is a URL or resource location for the archive containing -the functions. It can optionally use a `maven:` prefix to locate the artifact via a dependency lookup (see `FunctionProperties` -for complete details). A Spring Boot application is bootstrapped from the jar file, using the `MANIFEST.MF` to locate a start class, so -that a standard Spring Boot fat jar works well, for example. If the target jar can be launched successfully then the result is a function -registered in the main application's `FunctionCatalog`. The registered function can be applied by code in the main application, even though -it was created in an isolated class loader (by deault). - -Here is the example of deploying a JAR which contains an 'uppercase' function and invoking it . - -```java -@SpringBootApplication -public class DeployFunctionDemo { - - public static void main(String[] args) { - ApplicationContext context = SpringApplication.run(DeployFunctionDemo.class, - "--spring.cloud.function.location=..../target/uppercase-0.0.1-SNAPSHOT.jar", - "--spring.cloud.function.definition=uppercase"); - - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("uppercase"); - System.out.println(function.apply("hello")); - } -} -``` - -And here is the example using Maven URI (taken from one of the tests in `FunctionDeployerTests`): - -```java -@SpringBootApplication -public class DeployFunctionDemo { - - public static void main(String[] args) { - String[] args = new String[] { - "--spring.cloud.function.location=maven://oz.demo:demo-uppercase:0.0.1-SNAPSHOT", - "--spring.cloud.function.function-class=oz.demo.uppercase.MyFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("myFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - } -} -``` - -Keep in mind that Maven resource such as local and remote repositories, user, password and more are resolved using default MavenProperties which -effectively use local defaults and will work for majority of cases. However if you need to customize you can simply provide a bean of type -`MavenProperties` where you can set additional properties (see example below). - -```java -@Bean -public MavenProperties mavenProperties() { - MavenProperties properties = new MavenProperties(); - properties.setLocalRepository("target/it/"); - return properties; -} -``` - -[[supported-packaging-scenarios]] -== Supported Packaging Scenarios - -Currently Spring Cloud Function supports several packaging scenarios to give you the most flexibility when it comes to deploying functions. - -[[simple-jar]] -=== Simple JAR - -This packaging option implies no dependency on anything related to Spring. -For example; Consider that such JAR contains the following class: -```java -package function.example; -. . . -public class UpperCaseFunction implements Function { - @Override - public String apply(String value) { - return value.toUpperCase(); - } -} -``` -All you need to do is specify `location` and `function-class` properties when deploying such package: - -``` ---spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar ---spring.cloud.function.function-class=function.example.UpperCaseFunction -``` - -It's conceivable in some cases that you might want to package multiple functions together. For such scenarios you can use -`spring.cloud.function.function-class` property to list several classes delimiting them by `;`. - -For example, - -``` ---spring.cloud.function.function-class=function.example.UpperCaseFunction;function.example.ReverseFunction -``` - -Here we are identifying two functions to deploy, which we can now access in function catalog by name (e.g., `catalog.lookup("reverseFunction");`). - - -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/simplestjar[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L70[FunctionDeployerTests]. - -*** Component Scanning *** - -Since version 3.1.4 you can simplify your configuration thru component scanning feature described in <>. If you place your functional class in -package named `functions`, you can omit `spring.cloud.function.function-class` property as framework will auto-discover functional classes loading them in function catalog. -Keep in mind the naming convention to follow when doing function lookup. For example function class `functions.UpperCaseFunction` will be available in `FunctionCatalog` -under the name `upperCaseFunction`. - -[[spring-boot-jar]] -=== Spring Boot JAR - -This packaging option implies there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR -runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. -For example; Consider that such JAR contains the following class (which could have some additional Spring dependencies providing Spring/Spring Boot is on the classpath): -```java -package function.example; -. . . -public class UpperCaseFunction implements Function { - @Override - public String apply(String value) { - return value.toUpperCase(); - } -} -``` -As before all you need to do is specify `location` and `function-class` properties when deploying such package: - -``` ---spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar ---spring.cloud.function.function-class=function.example.UpperCaseFunction -``` -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootjar[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L50[FunctionDeployerTests]. - -[[spring-boot-application]] -=== Spring Boot Application - -This packaging option implies your JAR is complete stand alone Spring Boot application with functions as managed Spring beans. -As before there is an obvious assumption that there is a dependency on Spring Boot and that the JAR was generated as Spring Boot JAR. That said, given that the deployed JAR -runs in the isolated class loader, there will not be any version conflict with the Spring Boot version used by the actual deployer. -For example; Consider that such JAR contains the following class: -```java -package function.example; -. . . -@SpringBootApplication -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } -} -``` -Given that we're effectively dealing with another Spring Application context and that functions are spring managed beans, -in addition to the `location` property we also specify `definition` property instead of `function-class`. - -``` ---spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar ---spring.cloud.function.definition=uppercase -``` -For more details please reference the complete sample available https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-deployer/src/it/bootapp[here]. -You can also find a corresponding test in https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java#L164[FunctionDeployerTests]. - -NOTE: This particular deployment option may or may not have Spring Cloud Function on it's classpath. From the deployer perspective this doesn't matter. - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc b/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc deleted file mode 100644 index 1eb88819a..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/functional-bean-definitions.adoc +++ /dev/null @@ -1,6 +0,0 @@ -[[functional-bean-definitions]] -= Functional Bean Definitions -:page-section-summary-toc: 1 - -include:../:functional.adoc[leveloffset=+1] - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc b/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc deleted file mode 100644 index 8189dec01..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/getting-started.adoc +++ /dev/null @@ -1,6 +0,0 @@ -[[getting-started]] -= Getting Started -:page-section-summary-toc: 1 - -include:../:getting-started.adoc[] - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc b/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc deleted file mode 100644 index a5fa68562..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/introduction.adoc +++ /dev/null @@ -1,8 +0,0 @@ -[[introduction]] -= Introduction -:page-section-summary-toc: 1 - -include:../:_intro.adoc[] - -include:../:https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing-docs.adoc[] - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc b/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc deleted file mode 100644 index 7e00b2118..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/programming-model.adoc +++ /dev/null @@ -1,717 +0,0 @@ -[[programming-model]] -= Programming model - -[[function.catalog]] - -[[function-catalog-and-flexible-function-signatures]] -== Function Catalog and Flexible Function Signatures - -One of the main features of Spring Cloud Function is to adapt and support a range of type signatures for user-defined functions, -while providing a consistent execution model. -That's why all user defined functions are transformed into a canonical representation by `FunctionCatalog`. - -While users don't normally have to care about the `FunctionCatalog` at all, it is useful to know what -kind of functions are supported in user code. - -It is also important to understand that Spring Cloud Function provides first class support for reactive API -provided by https://projectreactor.io/[Project Reactor] allowing reactive primitives such as `Mono` and `Flux` -to be used as types in user defined functions providing greater flexibility when choosing programming model for -your function implementation. -Reactive programming model also enables functional support for features that would be otherwise difficult to impossible to implement -using imperative programming style. For more on this please read <> section. - -[[java-8-function-support]] -== Java 8 function support - -Spring Cloud Function embraces and builds on top of the 3 core functional interfaces defined by Java -and available to us since Java 8. - -- Supplier -- Function -- Consumer - -To avoid constantly mentioning `Supplier`, `Function` and `Consumer` we’ll refer to them a Functional beans for the rest of this manual where appropriate. - -In a nutshell, any bean in your Application Context that is Functional bean will lazily be registered with `FunctionCatalog`. -This means that it could benefit from all of the additional features described in this reference manual. - -In a simplest of application all you need to do is to declare `@Bean` of type `Supplier`, `Function` or `Consumer` in your application configuration. -Then you can access `FunctionCatalog` and lookup a particular function based on its name. - -For example: - - -[source, test] ----- -@Bean -public Function uppercase() { - return value -> value.toUpperCase(); -} - -. . . - -FunctionCatalog catalog = applicationContext.getBean(FunctionCatalog.class); -Function uppercase = catalog.lookup(“uppercase”); ----- - -Important to understand that given that `uppercase` is a bean, you can certainly get it form the `ApplicationContext` directly, but all you will get is just your bean as you declared it without any extra features provided by SCF. When you do lookup of a function via `FunctionCatalog`, the instance you will receive is wrapped (instrumented) with additional features (i.e., type conversion, composition etc.) described in this manual. Also, it is important to understand that a typical user does not use Spring Cloud Function directly. Instead a typical user implements Java `Function/Supplier/Consumer` with the idea of using it in different execution contexts without additional work. For example the same java function could be represented as _REST endpoint_ or _Streaming message handler_ or _AWS Lambda_ and more via Spring Cloud Function provided -adapters as well as other frameworks using Spring Cloud Function as the core programming model (e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]) -So in summary Spring Cloud Function instruments java functions with additional features to be utilised in variety of execution contexts. - - -[[function-definition]] -=== Function definition -While the previous example shows you how to lookup function in FunctionCatalog programmatically, in a typical integration case where Spring Cloud Function used as programming model by another framework (e.fg. Spring Cloud Stream), you declare which functions to use via `spring.cloud.function.definition` property. Knowing that it is important to understand some default behaviour when it comes to discovering functions in `FunctionCatalog`. For example, if you only have one Functional bean in your `ApplicationContext`, the `spring.cloud.function.definition` property typically will not be required, since a single function in `FunctionCatalog` can be looked up by an empty name or any name. For example, assuming that `uppercase` is the only function in your catalog, it can be looked up as `catalog.lookup(null)`, `catalog.lookup(“”)`, `catalog.lookup(“foo”)` -That said, for cases where you are using framework such as Spring Cloud Stream which uses `spring.cloud.function.definition` it is best practice and recommended to always use `spring.cloud.function.definition` property. - -For example, - -[source, test] ----- -spring.cloud.function.definition=uppercase ----- - -[[filtering-ineligible-functions]] -=== Filtering ineligible functions -A typical Application Context may include beans that are valid java functions, but not intended to be candidates to be registered with `FunctionCatalog`. -Such beans could be auto-configurations from other projects or any other beans that qualify to be Java functions. -The framework provides default filtering of known beans that should not be candidates for registration with function catalog. -You can also add to this list additional beans by providing coma delimited list of bean definition names using -`spring.cloud.function.ineligible-definitions` property. - -For example, - -[source, test] ----- -spring.cloud.function.ineligible-definitions=foo,bar ----- - -[[supplier]] -=== Supplier -Supplier can be _reactive_ - `Supplier>` -or _imperative_ - `Supplier`. From the invocation standpoint this should make no difference -to the implementor of such Supplier. However, when used within frameworks -(e.g., https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream]), Suppliers, especially reactive, -often used to represent the source of the stream, therefore they are invoked once to get the stream (e.g., Flux) -to which consumers can subscribe to. In other words such suppliers represent an equivalent of an _infinite stream_. -However, the same reactive suppliers can also represent _finite_ stream(s) (e.g., result set on the polled JDBC data). -In those cases such reactive suppliers must be hooked up to some polling mechanism of the underlying framework. - -To assist with that Spring Cloud Function provides a marker annotation -`org.springframework.cloud.function.context.PollableBean` to signal that such supplier produces a -finite stream and may need to be polled again. That said, it is important to understand that Spring Cloud Function itself -provides no behavior for this annotation. - -In addition `PollableBean` annotation exposes a _splittable_ attribute to signal that produced stream -needs to be split (see https://www.enterpriseintegrationpatterns.com/patterns/messaging/Sequencer.html[Splitter EIP]) - -Here is the example: - -[source, java] ----- -@PollableBean(splittable = true) -public Supplier> someSupplier() { - return () -> { - String v1 = String.valueOf(System.nanoTime()); - String v2 = String.valueOf(System.nanoTime()); - String v3 = String.valueOf(System.nanoTime()); - return Flux.just(v1, v2, v3); - }; -} ----- - -[[function]] -=== Function -Function can also be written in imperative or reactive way, yet unlike Supplier and Consumer there are -no special considerations for the implementor other then understanding that when used within frameworks -such as https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] and others, reactive function is -invoked only once to pass a reference to the stream (Flux or Mono) and imperative is invoked once per event. - -[[consumer]] -=== Consumer -Consumer is a little bit special because it has a `void` return type, -which implies blocking, at least potentially. Most likely you will not -need to write `Consumer>`, but if you do need to do that, -remember to subscribe to the input flux. - -[[function-composition]] -== Function Composition -Function Composition is a feature that allows one to compose several functions into one. -The core support is based on function composition feature available with https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#andThen-java.util.function.Function-[Function.andThen(..)] -support available since Java 8. However on top of it, we provide few additional features. - -[[declarative-function-composition]] -=== Declarative Function Composition - -This feature allows you to provide composition instruction in a declarative way using `|` (pipe) or `,` (comma) delimiter -when providing `spring.cloud.function.definition` property. - -For example ----- ---spring.cloud.function.definition=uppercase|reverse ----- -Here we effectively provided a definition of a single function which itself is a composition of -function `uppercase` and function `reverse`. In fact that is one of the reasons why the property name is _definition_ and not _name_, -since the definition of a function can be a composition of several named functions. -And as mentioned you can use `,` instead of pipe (such as `...definition=uppercase,reverse`). - -[[composing-non-functions]] -=== Composing non-Functions -Spring Cloud Function also supports composing Supplier with `Consumer` or `Function` as well as `Function` with `Consumer`. -What's important here is to understand the end product of such definitions. -Composing Supplier with Function still results in Supplier while composing Supplier with Consumer will effectively render Runnable. -Following the same logic composing Function with Consumer will result in Consumer. - -And of course you can't compose uncomposable such as Consumer and Function, Consumer and Supplier etc. - - -[[function-routing-and-filtering]] -== Function Routing and Filtering - -Since version 2.2 Spring Cloud Function provides routing feature allowing -you to invoke a single function which acts as a router to an actual function you wish to invoke -This feature is very useful in certain FAAS environments where maintaining configurations -for several functions could be cumbersome or exposing more than one function is not possible. - -The `RoutingFunction` is registered in _FunctionCatalog_ under the name `functionRouter`. For simplicity -and consistency you can also refer to `RoutingFunction.FUNCTION_NAME` constant. - -This function has the following signature: - -[source, java] ----- -public class RoutingFunction implements Function { -. . . -} ----- -The routing instructions could be communicated in several ways. We support providing instructions via Message headers, System -properties as well as pluggable strategy. So let's look at some of the details - -[[messageroutingcallback]] -=== MessageRoutingCallback - -The `MessageRoutingCallback` is a strategy to assist with determining the name of the route-to function definition. - -[source, java] ----- -public interface MessageRoutingCallback { - FunctionRoutingResult routingResult(Message message); - . . . -} ----- - -All you need to do is implement and register it as a bean to be picked up by the `RoutingFunction`. -For example: - -[source, java] ----- -@Bean -public MessageRoutingCallback customRouter() { - return new MessageRoutingCallback() { - @Override - public FunctionRoutingResult routingResult(Message message) { - return new FunctionRoutingResult((String) message.getHeaders().get("func_name")); - } - }; -} ----- - -In the preceding example you can see a very simple implementation of `MessageRoutingCallback` which determines the function definition from -`func_name` Message header of the incoming Message and returns the instance of `FunctionRoutingResult` containing the definition of function to invoke. - -*Message Headers* - -If the input argument is of type `Message`, you can communicate routing instruction by setting one of -`spring.cloud.function.definition` or `spring.cloud.function.routing-expression` Message headers. -As the name of the property suggests `spring.cloud.function.routing-expression` relies on Spring Expression Language (SpEL). -For more static cases you can use `spring.cloud.function.definition` header which allows you to provide -the name of a single function (e.g., `...definition=foo`) or a composition instruction (e.g., `...definition=foo|bar|baz`). -For more dynamic cases you can use `spring.cloud.function.routing-expression` header and provide SpEL expression that should resolve -into definition of a function (as described above). - -NOTE: SpEL evaluation context's root object is the -actual input argument, so in the case of `Message` you can construct expression that has access -to both `payload` and `headers` (e.g., `spring.cloud.function.routing-expression=headers.function_name`). - -IMPORTANT: SpEL allows user to provide string representation of Java code to be executed. Given that the `spring.cloud.function.routing-expression` could be provided via Message headers means that ability to set such expression could be exposed to the end user (i.e., HTTP Headers when using web module) which could result in some problems (e.g., malicious code). To manage that, all expressions coming via Message headers will only be evaluated against `SimpleEvaluationContext` which has limited functionality and designed to only evaluate the context object (Message in our case). On the other hand, all expressions that are set via property or system variable are evaluated against `StandardEvaluationContext`, which allows for full flexibility of Java language. -While setting expression via system/application property or environment variable is generally considered to be secure as it is not exposed to the end user in normal cases, there are cases where visibility as well as capability to update system, application and environment variables are indeed exposed to the end user via Spring Boot Actuator endpoints provided either by some of the Spring projects or third parties or custom implementation by the end user. Such endpoints must be secured using industry standard web security practices. -Spring Cloud Function does not expose any of such endpoints. - -In specific execution environments/models the adapters are responsible to translate and communicate -`spring.cloud.function.definition` and/or `spring.cloud.function.routing-expression` via Message header. -For example, when using _spring-cloud-function-web_ you can provide `spring.cloud.function.definition` as an HTTP -header and the framework will propagate it as well as other HTTP headers as Message headers. - -*Application Properties* - -Routing instruction can also be communicated via `spring.cloud.function.definition` -or `spring.cloud.function.routing-expression` as application properties. The rules described in the -previous section apply here as well. The only difference is you provide these instructions as -application properties (e.g., `--spring.cloud.function.definition=foo`). - -NOTE: It is important to understand that providing `spring.cloud.function.definition` -or `spring.cloud.function.routing-expression` as Message headers will only work for imperative functions (e.g., `Function`). -That is to say that we can _only_ route ***per-message*** with imperative functions. With reactive functions we can not route -***per-message***. Therefore you can only provide your routing instructions as Application Properties. -It's all about unit-of-work. In imperative function unit of work is Message so we can route based on such unit-of-work. -With reactive function unit-of-work is the entire stream, so we'll act only on the instruction provided via application -properties and route the entire stream. - -*Order of priority for routing instructions* - -Given that we have several mechanisms of providing routing instructions it is important to understand the priorities for -conflict resolutions in the event multiple mechanisms are used at the same time, so here is the order: - -1. `MessageRoutingCallback` (If function is imperative will take over regardless if anything else is defined) -2. Message Headers (If function is imperative and no `MessageRoutingCallback` provided) -3. Application Properties (Any function) - -*Unroutable Messages* - -In the event route-to function is not available in catalog you will get an exception stating that. - -There are cases when such behavior is not desired and you may want to have some "catch-all" type function which can handle such messages. -To accomplish that, framework provides `org.springframework.cloud.function.context.DefaultMessageRoutingHandler` strategy. All you need to do is register it as a bean. -Its default implementation will simply log the fact that the message is un-routable, but will allow message flow to proceed without the exception, effectively dropping the un-routable message. -If you want something more sophisticated all you need to do is provide your own implementation of this strategy and register it as a bean. - -[source, java] ----- -@Bean -public DefaultMessageRoutingHandler defaultRoutingHandler() { - return new DefaultMessageRoutingHandler() { - @Override - public void accept(Message message) { - // do something really cool - } - }; -} ----- - -[[function-filtering]] -=== Function Filtering -Filtering is the type of routing where there are only two paths - 'go' or 'discard'. In terms of functions it mean -you only want to invoke a certain function if some condition returns 'true', otherwise you want to discard input. -However, when it comes to discarding input there are many interpretation of what it could mean in the context of your application. -For example, you may want to log it, or you may want to maintain the counter of discarded messages. you may also want to do nothing at all. -Because of these different paths, we do not provide a general configuration option for how to deal with discarded messages. -Instead we simply recommend to define a simple Consumer which would signify the 'discard' path: - -[source, java] ----- -@Bean -public Consumer devNull() { - // log, count or whatever -} ----- -Now you can have routing expression that really only has two paths effectively becoming a filter. For example: - -[source, text] ----- ---spring.cloud.function.routing-expression=headers.contentType.toString().equals('text/plain') ? 'echo' : 'devNull' ----- -Every message that does not fit criteria to go to 'echo' function will go to 'devNull' where you can simply do nothing with it. -The signature `Consumer` will also ensure that no type conversion will be attempted resulting in almost no execution overhead. - - -IMPORTANT: When dealing with reactive inputs (e.g., Publisher), routing instructions must only be provided via Function properties. This is -due to the nature of the reactive functions which are invoked only once to pass a Publisher and the rest -is handled by the reactor, hence we can not access and/or rely on the routing instructions communicated via individual -values (e.g., Message). - -[[multiple-routers]] -=== Multiple Routers - -By default the framework will always have a single routing function configured as described in previous sections. However, there are times when you may need more than one routing function. -In that case you can create your own instance of the `RoutingFunction` bean in addition to the existing one as long as you give it a name other than `functionRouter`. - -You can pass `spring.cloud.function.routing-expression` or `spring.cloud.function.definition` to RoutinFunction as key/value pairs in the map. - -Here is a simple example - ----- -@Configuration -protected static class MultipleRouterConfiguration { - - @Bean - RoutingFunction mySpecialRouter(FunctionCatalog functionCatalog, BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) { - Map propertiesMap = new HashMap<>(); - propertiesMap.put(FunctionProperties.PREFIX + ".routing-expression", "'reverse'"); - return new RoutingFunction(functionCatalog, propertiesMap, new BeanFactoryResolver(beanFactory), routingCallback); - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function uppercase() { - return String::toUpperCase; - } -} ----- - -and a test that demonstrates how it works - -` ----- -@Test -public void testMultipleRouters() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "'uppercase'"); - FunctionCatalog functionCatalog = this.configureCatalog(MultipleRouterConfiguration.class); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("HELLO"); - - function = functionCatalog.lookup("mySpecialRouter"); - assertThat(function).isNotNull(); - message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); -} ----- - -[[input/output-enrichment]] -== Input/Output Enrichment - -There are often times when you need to modify or refine an incoming or outgoing Message and to keep your code clean of non-functional concerns. You don’t want to do it inside of your business logic. - -You can always accomplish it via <>. Such approach provides several benefits: - -- It allows you to isolate this non-functional concern into a separate function which you can compose with the business function as function definition. -- It provides you with complete freedom (and danger) as to what you can modify before incoming message reaches the actual business function. - -[source, java] ----- -@Bean -public Function, Message> enrich() { - return message -> MessageBuilder.fromMessage(message).setHeader("foo", "bar").build(); -} - -@Bean -public Function, Message> myBusinessFunction() { - // do whatever -} ----- - -And then compose your function by providing the following function definition `enrich|myBusinessFunction`. - -While the described approach is the most flexible, it is also the most involved as it requires you to write some code, make it a bean or -manually register it as a function before you can compose it with the business function as you can see from the preceding example. - -But what if modifications (enrichments) you are trying to make are trivial as they are in the preceding example? Is there a simpler and more dynamic and configurable - mechanism to accomplish the same? - -Since version 3.1.3, the framework allows you to provide SpEL expression to enrich individual message headers for both input going into function and -and output coming out of it. Let’s look at one of the tests as the example. - -[source, java] ----- -@Test -public void testMixedInputOutputHeaderMapping() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut1='hello1'", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut2=headers.contentType", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key1=headers.path.split('/')[0]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key2=headers.path.split('/')[1]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key3=headers.path")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("split"); - Message result = (Message) function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setHeader("path", "foo/bar/baz").build()); - assertThat(result.getHeaders().containsKey("keyOut1")).isTrue(); - assertThat(result.getHeaders().get("keyOut1")).isEqualTo("hello1"); - assertThat(result.getHeaders().containsKey("keyOut2")).isTrue(); - assertThat(result.getHeaders().get("keyOut2")).isEqualTo("application/json"); - } -} ----- - -Here you see a properties called `input-header-mapping-expression` and `output-header-mapping-expression` preceded by the name of the function (i.e., `split`) and followed by the name of the message header key you want to set and the value as SpEL expression. The first expression (for 'keyOut1') is literal SpEL expressions enclosed in single quotes, effectively setting 'keyOut1' to value `hello1`. The `keyOut2` is set to the value of existing 'contentType' header. - -You can also observe some interesting features in the input header mapping where we actually splitting a value of the existing header 'path', setting individual values of key1 and key2 to the values of split elements based on the index. - -NOTE: if for whatever reason the provided expression evaluation fails, the execution of the function will proceed as if nothing ever happen. -However you will see the WARN message in your logs informing you about it - -[source, text] ----- -o.s.c.f.context.catalog.InputEnricher : Failed while evaluating expression "hello1" on incoming message. . . ----- - -In the event you are dealing with functions that have multiple inputs (next section), you can use index immediately after `input-header-mapping-expression` - -[source, text] ----- ---spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1=‘hello1' ---spring.cloud.function.configuration.echo.input-header-mapping-expression[1].key2='hello2' ----- - -[[function-arity]] -== Function Arity - -There are times when a stream of data needs to be categorized and organized. For example, -consider a classic big-data use case of dealing with unorganized data containing, let’s say, -‘orders’ and ‘invoices’, and you want each to go into a separate data store. -This is where function arity (functions with multiple inputs and outputs) support -comes to play. - -Let’s look at an example of such a function (full implementation details are available -https://github.com/spring-cloud/spring-cloud-stream/blob/master/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/MultipleInputOutputFunctionTests.java#L342[here]), - -[source, java] ----- -@Bean -public Function, Tuple2, Flux>> organise() { - return flux -> ...; -} ----- - -Given that Project Reactor is a core dependency of SCF, we are using its Tuple library. -Tuples give us a unique advantage by communicating to us both _cardinality_ and _type_ information. -Both are extremely important in the context of SCSt. Cardinality lets us know -how many input and output bindings need to be created and bound to the corresponding -inputs and outputs of a function. Awareness of the type information ensures proper type -conversion. - -Also, this is where the ‘index’ part of the naming convention for binding -names comes into play, since, in this function, the two output binding -names are `organise-out-0` and `organise-out-1`. - -IMPORTANT: IMPORTANT: At the moment, function arity is *only* supported for reactive functions -(`Function...>, TupleN...>>`) centered on Complex event processing -where evaluation and computation on confluence of events typically requires view into a -stream of events rather than single event. - -[[input-header-propagation]] -== Input Header propagation - -In a typical scenario input Message headers are not propagated to output and rightfully so, since the output of a function may be an input to something else requiring it's own set of Message headers. -However, there are times when such propagation may be necessary so Spring Cloud Function provides several mechanisms to accomplish this. - -First you can always copy headers manually. For example, if you have a Function with the signature that takes `Message` and returns `Message` (i.e., `Function`), you can simply and selectively copy headers yourselves. Remember, if your function returns Message, the framework will not do anything to it other then properly converting its payload. -However, such approach may prove to be a bit tedious, especially in cases when you simply want to copy all headers. -To assist with cases like this we provide a simple property that would allow you to set a boolean flag on a function where you want input headers to be propagated. -The property is `copy-input-headers`. - -For example, let's assume you have the following configuration: - -[source, java] ----- -@EnableAutoConfiguration -@Configuration -protected static class InputHeaderPropagationConfiguration { - - @Bean - public Function uppercase() { - return x -> x.toUpperCase(); - } -} ----- - -As you know you can still invoke this function by sending a Message to it (framework will take care of type conversion and payload extraction) - -By simply setting `spring.cloud.function.configuration.uppercase.copy-input-headers` to `true`, the following assertion will be true as well - ----- -Function, Message> uppercase = catalog.lookup("uppercase", "application/json"); -Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHeader("foo", "bar").build()); -assertThat(result.getHeaders()).containsKey("foo"); ----- - -[[type-conversion-content-type-negotiation]] -== Type conversion (Content-Type negotiation) - -Content-Type negotiation is one of the core features of Spring Cloud Function as it allows to not only transform the incoming data to the types declared -by the function signature, but to do the same transformation during function composition making otherwise un-composable (by type) functions composable. - -To better understand the mechanics and the necessity behind content-type negotiation, we take a look at a very simple use case by -using the following function as an example: - -[source, java] ----- -@Bean -public Function personFunction {..} ----- - -The function shown in the preceding example expects a `Person` object as an argument and produces a String type as an output. If such function is -invoked with the type `Person`, than all works fine. But typically function plays a role of a handler for the incoming data which most often comes -in the raw format such as `byte[]`, `JSON String` etc. In order for the framework to succeed in passing the incoming data as an argument to -this function, it has to somehow transform the incoming data to a `Person` type. - -Spring Cloud Function relies on two native to Spring mechanisms to accomplish that. - -. _MessageConverter_ - to convert from incoming Message data to a type declared by the function. -. _ConversionService_ - to convert from incoming non-Message data to a type declared by the function. - -This means that depending on the type of the raw data (Message or non-Message) Spring Cloud Function will apply one or the other mechanisms. - -For most cases when dealing with functions that are invoked as part of some other request (e.g., HTTP, Messaging etc) the framework relies on `MessageConverters`, -since such requests already converted to Spring `Message`. In other words, the framework locates and applies the appropriate `MessageConverter`. -To accomplish that, the framework needs some instructions from the user. One of these instructions is already provided by the signature of the function -itself (Person type). Consequently, in theory, that should be (and, in some cases, is) enough. However, for the majority of use cases, in order to -select the appropriate `MessageConverter`, the framework needs an additional piece of information. That missing piece is `contentType` header. - -Such header usually comes as part of the Message where it is injected by the corresponding adapter that created such Message in the first place. -For example, HTTP POST request will have its content-type HTTP header copied to `contentType` header of the Message. - -For cases when such header does not exist framework relies on the default content type as `application/json`. - - -[[content-type-versus-argument-type]] -=== Content Type versus Argument Type - -As mentioned earlier, for the framework to select the appropriate `MessageConverter`, it requires argument type and, optionally, content type information. -The logic for selecting the appropriate `MessageConverter` resides with the argument resolvers which trigger right before the invocation of the user-defined -function (which is when the actual argument type is known to the framework). -If the argument type does not match the type of the current payload, the framework delegates to the stack of the -pre-configured `MessageConverters` to see if any one of them can convert the payload. - -The combination of `contentType` and argument type is the mechanism by which framework determines if message can be converted to a target type by locating -the appropriate `MessageConverter`. -If no appropriate `MessageConverter` is found, an exception is thrown, which you can handle by adding a custom `MessageConverter` -(see `xref:spring-cloud-function/programming-model.adoc#user-defined-message-converters[User-defined Message Converters]`). - -NOTE: Do not expect `Message` to be converted into some other type based only on the `contentType`. -Remember that the `contentType` is complementary to the target type. -It is a hint, which `MessageConverter` may or may not take into consideration. - -[[message-converters]] -=== Message Converters - -`MessageConverters` define two methods: - -[source, java] ----- -Object fromMessage(Message message, Class targetClass); - -Message toMessage(Object payload, @Nullable MessageHeaders headers); ----- - -It is important to understand the contract of these methods and their usage, specifically in the context of Spring Cloud Stream. - -The `fromMessage` method converts an incoming `Message` to an argument type. -The payload of the `Message` could be any type, and it is -up to the actual implementation of the `MessageConverter` to support multiple types. - - -[[provided-messageconverters]] -=== Provided MessageConverters - -As mentioned earlier, the framework already provides a stack of `MessageConverters` to handle most common use cases. -The following list describes the provided `MessageConverters`, in order of precedence (the first `MessageConverter` that works is used): - -. `JsonMessageConverter`: Supports conversion of the payload of the `Message` to/from POJO for cases when `contentType` is `application/json` using Jackson (DEFAULT) or Gson libraries. This message converter also aware of `type` parameter (e.g., _application/json;type=foo.bar.Person_). This is useful for cases where types may not be known at the time when function is developed, hence function signature may look like `Function` or `Function` or `Function`. In other words for type conversion we typically derive type from function signature. Having, mime-type parameter allows you to communicate type in a more dynamic way. -. `ByteArrayMessageConverter`: Supports conversion of the payload of the `Message` from `byte[]` to `byte[]` for cases when `contentType` is `application/octet-stream`. It is essentially a pass through and exists primarily for backward compatibility. -. `StringMessageConverter`: Supports conversion of any type to a `String` when `contentType` is `text/plain`. - -When no appropriate converter is found, the framework throws an exception. When that happens, you should check your code and configuration and ensure you did -not miss anything (that is, ensure that you provided a `contentType` by using a binding or a header). -However, most likely, you found some uncommon case (such as a custom `contentType` perhaps) and the current stack of provided `MessageConverters` -does not know how to convert. If that is the case, you can add custom `MessageConverter`. See xref:spring-cloud-function/programming-model.adoc#user-defined-message-converters[User-defined Message Converters]. - -[[user-defined-message-converters]] -=== User-defined Message Converters - -Spring Cloud Function exposes a mechanism to define and register additional `MessageConverters`. -To use it, implement `org.springframework.messaging.converter.MessageConverter`, configure it as a `@Bean`. -It is then appended to the existing stack of `MessageConverter`s. - -NOTE: It is important to understand that custom `MessageConverter` implementations are added to the head of the existing stack. -Consequently, custom `MessageConverter` implementations take precedence over the existing ones, which lets you override as well as add to the existing converters. - -The following example shows how to create a message converter bean to support a new content type called `application/bar`: - -[source,java] ----- -@SpringBootApplication -public static class SinkApplication { - - ... - - @Bean - public MessageConverter customMessageConverter() { - return new MyCustomMessageConverter(); - } -} - -public class MyCustomMessageConverter extends AbstractMessageConverter { - - public MyCustomMessageConverter() { - super(new MimeType("application", "bar")); - } - - @Override - protected boolean supports(Class clazz) { - return (Bar.class.equals(clazz)); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, Object conversionHint) { - Object payload = message.getPayload(); - return (payload instanceof Bar ? payload : new Bar((byte[]) payload)); - } -} ----- - -[[note-on-json-options]] -=== Note on JSON options - -In Spring Cloud Function we support Jackson and Gson mechanisms to deal with JSON. -And for your benefit have abstracted it under `org.springframework.cloud.function.json.JsonMapper` which itself is aware of two mechanisms and will use the one selected -by you or following the default rule. -The default rules are as follows: - -* Whichever library is on the classpath that is the mechanism that is going to be used. So if you have `com.fasterxml.jackson.*` to the classpath, Jackson is going to be used and if you have `com.google.code.gson`, then Gson will be used. -* If you have both, then Gson will be the default, or you can set `spring.cloud.function.preferred-json-mapper` property with either of two values: `gson` or `jackson`. - - -That said, the type conversion is usually transparent to the developer, however given that `org.springframework.cloud.function.json.JsonMapper` is also registered as a bean -you can easily inject it into your code if needed. - - -[[kotlin-lambda-support]] -== Kotlin Lambda support - -We also provide support for Kotlin lambdas (since v2.0). -Consider the following: - -[source, java] ----- -@Bean -open fun kotlinSupplier(): () -> String { - return { "Hello from Kotlin" } -} - -@Bean -open fun kotlinFunction(): (String) -> String { - return { it.toUpperCase() } -} - -@Bean -open fun kotlinConsumer(): (String) -> Unit { - return { println(it) } -} - ----- -The above represents Kotlin lambdas configured as Spring beans. The signature of each maps to a Java equivalent of -`Supplier`, `Function` and `Consumer`, and thus supported/recognized signatures by the framework. -While mechanics of Kotlin-to-Java mapping are outside of the scope of this documentation, it is important to understand that the -same rules for signature transformation outlined in "Java 8 function support" section are applied here as well. - -To enable Kotlin support all you need is to add Kotlin SDK libraries on the classpath which will trigger appropriate -autoconfiguration and supporting classes. - -[[function-component-scan]] -== Function Component Scan - -Spring Cloud Function will scan for implementations of `Function`, `Consumer` and `Supplier` in a package called `functions` if it exists. Using this -feature you can write functions that have no dependencies on Spring - not even the `@Component` annotation is needed. If you want to use a different -package, you can set `spring.cloud.function.scan.packages`. You can also use `spring.cloud.function.scan.enabled=false` to switch off the scan completely. - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc b/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc deleted file mode 100644 index f6ff9b284..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/serverless-platform-adapters.adoc +++ /dev/null @@ -1,15 +0,0 @@ -[[serverless-platform-adapters]] -= Serverless Platform Adapters -:page-section-summary-toc: 1 - -As well as being able to run as a standalone process, a Spring Cloud -Function application can be adapted to run one of the existing -serverless platforms. In the project there are adapters for -https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS -Lambda], and https://github.com/spring-cloud/spring-cloud-function/tree/{branch}/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure]. The https://github.com/fnproject/fn[Oracle Fn platform] has its own Spring Cloud Function adapter. And https://projectriff.io[Riff] supports Java functions and its -https://github.com/projectriff/java-function-invoker[Java Function Invoker] acts natively is an adapter for Spring Cloud Function jars. - -include:../:adapters/aws-intro.adoc[] -include:../:adapters/azure-intro.adoc[leveloffset=+1] -include:../:adapters/gcp-intro.adoc[] - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc b/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc deleted file mode 100644 index a50539b28..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/standalone-streaming-applications.adoc +++ /dev/null @@ -1,7 +0,0 @@ -[[standalone-streaming-applications]] -= Standalone Streaming Applications -:page-section-summary-toc: 1 - -To send or receive messages from a broker (such as RabbitMQ or Kafka) you can leverage `spring-cloud-stream` project and it's integration with Spring Cloud Function. -Please refer to https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/current/reference/html/spring-cloud-stream.html#spring_cloud_function[Spring Cloud Function] section of the https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] reference manual for more details and examples. - diff --git a/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc b/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc deleted file mode 100644 index 442989230..000000000 --- a/docs/modules/ROOT/pages/spring-cloud-function/standalone-web-applications.adoc +++ /dev/null @@ -1,120 +0,0 @@ -[[standalone-web-applications]] -= Standalone Web Applications - -Functions could be automatically exported as HTTP endpoints. - -The `spring-cloud-function-web` module has autoconfiguration that -activates when it is included in a Spring Boot web application (with -MVC support). There is also a `spring-cloud-starter-function-web` to -collect all the optional dependencies in case you just want a simple -getting started experience. - -With the web configurations activated your app will have an MVC -endpoint (on "/" by default, but configurable with -`spring.cloud.function.web.path`) that can be used to access the -functions in the application context where function name becomes part of the URL path. The supported content types are -plain text and JSON. - -IMPORTANT: It is important to understand that while SCF provides ability to export Functional beans as REST endpoints it is NOT a replacement for Spring MVC/WebFlux etc. -It is primarily to accommodate _stateless serverless patterns_ where you simply want to have some stateless functionality to be exposed via HTTP. - -|=== -| Method | Path | Request | Response | Status - -| GET | /{supplier} | - | Items from the named supplier | 200 OK -| POST | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted -| PUT | /{consumer} | JSON object or text | Mirrors input and pushes request body into consumer | 202 Accepted -| DELETE | /{consumer} | JSON object or text | - | 204 NO CONTENT -| POST | /{function} | JSON object or text | The result of applying the named function | 200 OK -| PUT | /{function} | JSON object or text | The result of applying the named function | 200 OK -| GET | /{function}/{item} | - | Convert the item into an object and return the result of applying the function | 200 OK - -|=== - -As the table above shows the behavior of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or `Flux`), then the response will also contain a single value. -For multi-valued responses the client can ask for a server-sent event stream by sending `Accept: text/event-stream`. - -Functions and consumers that are declared with input and output in `Message` will see the request headers as _message headers_, and the output _message headers_ will be converted to HTTP headers. -The _payload_ of the Message will be a `body` or empty string if there is no `body` or it is null. - -When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accept headers for the best results). - -See <> to see the details and example on how to test such application. - -[[http-request-parameters]] -=== HTTP Request Parameters -As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., `/{function}/{item}`). -For example, `http://localhost:8080/uppercase/foo` will result in calling `uppercase` function with its input parameter being `foo`. - -While this is the recommended approach and the one that fits most use cases cases, there are times when you have to deal with HTTP request parameters (e.g., `http://localhost:8080/uppercase/foo?name=Bill`) -The framework will treat HTTP request parameters similar to the HTTP headers by storing them in the `Message` headers under the header key `http_request_param` -with its value being a `Map` of request parameters, so in order to access them your function input signature should accept `Message` type (e.g., `Function, String>`). For convenience we provide `HeaderUtils.HTTP_REQUEST_PARAM` constant. - -[[function-mapping-rules]] -== Function Mapping rules - -If there is only a single function (consumer etc.) in the catalog, the name in the path is optional. -In other words, providing you only have `uppercase` function in catalog -`curl -H "Content-Type: text/plain" localhost:8080/uppercase -d hello` and `curl -H "Content-Type: text/plain" localhost:8080/ -d hello` calls are identical. - -Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line). -For example, `curl -H "Content-Type: text/plain" localhost:8080/uppercase,reverse -d hello`. - -For cases where there is more than a single function in catalog, each function will be exported and mapped with function name being -part of the path (e.g., `localhost:8080/uppercase`). -In this scenario you can still map specific function or function composition to the root path by providing -`spring.cloud.function.definition` property - -For example, ----- ---spring.cloud.function.definition=foo|bar ----- - -The above property will compose 'foo' and 'bar' function and map the composed function to the "/" path. - -The same property will also work for cases where function can not be resolved via URL. For example, your URL may be `localhost:8080/uppercase`, but there is no `uppercase` function. -However there are function `foo` and `bar`. So, in this case `localhost:8080/uppercase` will resolve to `foo|bar`. -This could be useful especially for cases when URL is used to communicate certain information since there will be Message header called `uri` with the value -of the actual URL, giving user ability to use it for evaluation and computation. - -[[function-filtering-rules]] -== Function Filtering rules - -In situations where there are more than one function in catalog there may be a need to only export certain functions or function compositions. In that case you can use -the same `spring.cloud.function.definition` property listing functions you intend to export delimited by `;`. -Note that in this case nothing will be mapped to the root path and functions that are not listed (including compositions) are not going to be exported - -For example, - ----- ---spring.cloud.function.definition=foo;bar ----- - -This will only export function `foo` and function `bar` regardless how many functions are available in catalog (e.g., `localhost:8080/foo`). - ----- ---spring.cloud.function.definition=foo|bar;baz ----- - -This will only export function composition `foo|bar` and function `baz` regardless how many functions are available in catalog (e.g., `localhost:8080/foo,bar`). - -[[crud-rest-with-spring-cloud-function]] -== CRUD REST with Spring Cloud Function - -By now it should be clear that functions are exported as REST endpoints and can be invoked using various HTTP methods. In other words a single -function could be triggered via GET, POST, PUT etc. - -However, it is not always desirable and certainly does not fit the CRUD concept. And while SCF does not support and has no intention of supporting -all the features of Spring web stack, the framework does provide support for CRUD mappings where a single function could be mapped to a particular HTTP method(s). -It is done via spring.cloud.function.http. property. - -For example, - ----- -spring.cloud.function.http.GET=uppercase;reverse;foo|bar -spring.cloud.function.http.POST=reverse -spring.cloud.function.http.DELETE=deleteById ----- - -As you can see, here we’re mapping functions to various HTTP methods using the same rules as `spring.cloud.function.definition` property where “;” allows us to define several functions and “|” signifies function composition. - diff --git a/docs/modules/ROOT/pages/spring-integration.adoc b/docs/modules/ROOT/pages/spring-integration.adoc deleted file mode 100644 index 670aa8d98..000000000 --- a/docs/modules/ROOT/pages/spring-integration.adoc +++ /dev/null @@ -1,101 +0,0 @@ -[[spring-integration]] -= Spring Integration Interaction - -https://spring.io/projects/spring-integration[Spring Integration Framework] extends the Spring programming model to support the well-known Enterprise Integration Patterns. -It enables lightweight messaging within Spring-based applications and supports integration with external systems via declarative adapters. -It also provides a high-level DSL to compose various operations (endpoints) into a logical integration flow. -With a lambda style of this DSL configuration, Spring Integration already has a good level of `java.util.function` interfaces adoption. -The `@MessagingGateway` proxy interface can also be as a `Function` or `Consumer`, which according to the Spring Cloud Function environment can be registered into a function catalog. -See more information in Spring Integration https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#functions-support[ReferenceManual] about its support for functions. - -On the other hand, starting with version `4.0.3`, Spring Cloud Function introduces a `spring-cloud-function-integration` module which provides deeper, more cloud-specific and auto-configuration based API for interaction with a `FunctionCatalog` from Spring Integration DSL perspective. -The `FunctionFlowBuilder` is auto-configured and autowired with a `FunctionCatalog` and represents an entry point for function-specific DSL for target `IntegrationFlow` instance. -In addition to standard `IntegrationFlow.from()` factories (for convenience), the `FunctionFlowBuilder` exposes a `fromSupplier(String supplierDefinition)` factory to lookup the target `Supplier` in the provided `FunctionCatalog`. -Then this `FunctionFlowBuilder` leads to the `FunctionFlowDefinition`. -This `FunctionFlowDefinition` is an implementation of the `IntegrationFlowExtension` and exposes `apply(String functionDefinition)` and `accept(String consumerDefinition)` operators to lookup `Function` or `Consumer` from the `FunctionCatalog`, respectively. -See their Javadocs for more information. - -The following example demonstrates the `FunctionFlowBuilder` in action alongside with the power of the rest of `IntegrationFlow` API: - -[source,java] ----- -@Configuration -public class IntegrationConfiguration { - - @Bean - Supplier simpleByteArraySupplier() { - return "simple test data"::getBytes; - } - - @Bean - Function upperCaseFunction() { - return String::toUpperCase; - } - - @Bean - BlockingQueue results() { - return new LinkedBlockingQueue<>(); - } - - @Bean - Consumer simpleStringConsumer(BlockingQueue results) { - return results::add; - } - - @Bean - QueueChannel wireTapChannel() { - return new QueueChannel(); - } - - @Bean - IntegrationFlow someFunctionFlow(FunctionFlowBuilder functionFlowBuilder) { - return functionFlowBuilder - .fromSupplier("simpleByteArraySupplier") - .wireTap("wireTapChannel") - .apply("upperCaseFunction") - .log(LoggingHandler.Level.WARN) - .accept("simpleStringConsumer"); - } - -} ----- - -Since the `FunctionCatalog.lookup()` functionality is not limited just to simple function names, a function composition feature can also be used in the mentioned `apply()` and `accept()` operators: - -[source,java] ----- -@Bean -IntegrationFlow functionCompositionFlow(FunctionFlowBuilder functionFlowBuilder) { - return functionFlowBuilder - .from("functionCompositionInput") - .accept("upperCaseFunction|simpleStringConsumer"); -} ----- - -This API becomes more relevant, when we add into our Spring Cloud applications auto-configuration dependencies for predefined functions. -For example https://spring.io/projects/spring-cloud-stream-applications[Stream Applications] project, in addition to application images, provides artifacts with functions for various integration use-case, e.g. `debezium-supplier`, `elasticsearch-consumer`, `aggregator-function` etc. - -The following configuration is based on the `http-supplier`, `spel-function` and `file-consumer`, respectively: - -[source,java] ----- -@Bean -IntegrationFlow someFunctionFlow(FunctionFlowBuilder functionFlowBuilder) { - return functionFlowBuilder - .fromSupplier("httpSupplier", e -> e.poller(Pollers.trigger(new OnlyOnceTrigger()))) - .>handle((fluxPayload, headers) -> fluxPayload, e -> e.async(true)) - .channel(c -> c.flux()) - .apply("spelFunction") - .transform(String::toUpperCase) - .accept("fileConsumer"); -} ----- - -What we would need else is just to add their configuration into an `application.properties` (if necessary): - -[source,properties] ----- -http.path-pattern=/testPath -spel.function.expression=new String(payload) -file.consumer.name=test-data.txt ----- diff --git a/docs/pom.xml b/docs/pom.xml deleted file mode 100644 index 35f1d5e4a..000000000 --- a/docs/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 4.0.0 - spring-cloud-function-docs - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - pom - Spring Cloud Function Docs - Spring Cloud Function Docs - - spring-cloud-function - ${basedir}/.. - 3.4 - deploy - - - - docs - - - - pl.project13.maven - git-commit-id-plugin - - - org.apache.maven.plugins - maven-dependency-plugin - - - org.apache.maven.plugins - maven-resources-plugin - - - org.codehaus.mojo - exec-maven-plugin - - - org.asciidoctor - asciidoctor-maven-plugin - - - ${project.version} - ${spring-boot.version} - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - org.codehaus.mojo - build-helper-maven-plugin - - - maven-deploy-plugin - - - - - - diff --git a/docs/src/main/asciidoc/ghpages.sh b/docs/src/main/asciidoc/ghpages.sh deleted file mode 100755 index 2562c7171..000000000 --- a/docs/src/main/asciidoc/ghpages.sh +++ /dev/null @@ -1,330 +0,0 @@ -#!/bin/bash -x - -set -e - -# Set default props like MAVEN_PATH, ROOT_FOLDER etc. -function set_default_props() { - # The script should be executed from the root folder - ROOT_FOLDER=`pwd` - echo "Current folder is ${ROOT_FOLDER}" - - if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then - echo "You're not in the root folder of the project!" - exit 1 - fi - - # Prop that will let commit the changes - COMMIT_CHANGES="no" - MAVEN_PATH=${MAVEN_PATH:-} - echo "Path to Maven is [${MAVEN_PATH}]" - REPO_NAME=${PWD##*/} - echo "Repo name is [${REPO_NAME}]" - SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git} - echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}" -} - -# Check if gh-pages exists and docs have been built -function check_if_anything_to_sync() { - git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'` - - if ! (git remote set-branches --add origin gh-pages && git fetch -q); then - echo "No gh-pages, so not syncing" - exit 0 - fi - - if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then - echo "No gh-pages sources in docs/target/generated-docs, so not syncing" - exit 0 - fi -} - -function retrieve_current_branch() { - # Code getting the name of the current branch. For master we want to publish as we did until now - # https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch - # If there is a branch already passed will reuse it - otherwise will try to find it - CURRENT_BRANCH=${BRANCH} - if [[ -z "${CURRENT_BRANCH}" ]] ; then - CURRENT_BRANCH=$(git symbolic-ref -q HEAD) - CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/} - CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD} - fi - echo "Current branch is [${CURRENT_BRANCH}]" - git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" -} - -# Switches to the provided value of the release version. We always prefix it with `v` -function switch_to_tag() { - git checkout v${VERSION} -} - -# Build the docs if switch is on -function build_docs_if_applicable() { - if [[ "${BUILD}" == "yes" ]] ; then - ./mvnw clean install -P docs -pl docs -DskipTests - fi -} - -# Get the name of the `docs.main` property -# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile -function retrieve_doc_properties() { - MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \ - -Dexec.executable="echo" \ - -Dexec.args='${docs.main}' \ - --non-recursive \ - org.codehaus.mojo:exec-maven-plugin:1.3.1:exec) - echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]" - - - WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"} - WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \ - -Dexec.executable="echo" \ - -Dexec.args="\${${WHITELIST_PROPERTY}}" \ - org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \ - -P docs \ - -pl docs) - echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]" -} - -# Stash any outstanding changes -function stash_changes() { - git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1") - if [ "$dirty" != "0" ]; then git stash; fi -} - -# Switch to gh-pages branch to sync it with current branch -function add_docs_from_target() { - local DESTINATION_REPO_FOLDER - if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then - DESTINATION_REPO_FOLDER=${ROOT_FOLDER} - elif [[ "${CLONE}" == "yes" ]]; then - mkdir -p ${ROOT_FOLDER}/target - local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static - if [[ ! -e "${clonedStatic}/.git" ]]; then - echo "Cloning Spring Cloud Static to target" - git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages - else - echo "Spring Cloud Static already cloned - will pull changes" - cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages - fi - DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME} - mkdir -p ${DESTINATION_REPO_FOLDER} - else - if [[ ! -e "${DESTINATION}/.git" ]]; then - echo "[${DESTINATION}] is not a git repository" - exit 1 - fi - DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME} - mkdir -p ${DESTINATION_REPO_FOLDER} - echo "Destination was provided [${DESTINATION}]" - fi - cd ${DESTINATION_REPO_FOLDER} - git checkout gh-pages - git pull origin gh-pages - - # Add git branches - ################################################################### - if [[ -z "${VERSION}" ]] ; then - copy_docs_for_current_version - else - copy_docs_for_provided_version - fi - commit_changes_if_applicable -} - - -# Copies the docs by using the retrieved properties from Maven build -function copy_docs_for_current_version() { - if [[ "${CURRENT_BRANCH}" == "master" ]] ; then - echo -e "Current branch is master - will copy the current docs only to the root folder" - for f in docs/target/generated-docs/*; do - file=${f#docs/target/generated-docs/*} - if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then - # Not ignored... - cp -rf $f ${ROOT_FOLDER}/ - git add -A ${ROOT_FOLDER}/$file - fi - done - COMMIT_CHANGES="yes" - else - echo -e "Current branch is [${CURRENT_BRANCH}]" - # https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin - if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then - mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH} - echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder" - for f in docs/target/generated-docs/*; do - file=${f#docs/target/generated-docs/*} - if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then - # Not ignored... - # We want users to access 2.0.0.BUILD-SNAPSHOT/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html - if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then - # We don't want to copy the spring-cloud-sleuth.html - # we want it to be converted to index.html - cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html - git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html - else - cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH} - git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file - fi - fi - done - COMMIT_CHANGES="yes" - else - echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in - [docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch." - fi - fi -} - -# Copies the docs by using the explicitly provided version -function copy_docs_for_provided_version() { - local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION} - mkdir -p ${FOLDER} - echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder" - for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do - file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*} - copy_docs_for_branch ${file} ${FOLDER} - done - COMMIT_CHANGES="yes" - CURRENT_BRANCH="v${VERSION}" -} - -# Copies the docs from target to the provided destination -# Params: -# $1 - file from target -# $2 - destination to which copy the files -function copy_docs_for_branch() { - local file=$1 - local destination=$2 - if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then - # Not ignored... - # We want users to access 2.0.0.BUILD-SNAPSHOT/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html - if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then - # We don't want to copy the spring-cloud-sleuth.html - # we want it to be converted to index.html - cp -rf $f ${destination}/index.html - git add -A ${destination}/index.html - else - cp -rf $f ${destination} - git add -A ${destination}/$file - fi - fi -} - -function commit_changes_if_applicable() { - if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then - COMMIT_SUCCESSFUL="no" - git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes" - - # Uncomment the following push if you want to auto push to - # the gh-pages branch whenever you commit to master locally. - # This is a little extreme. Use with care! - ################################################################### - if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then - git push origin gh-pages - fi - fi -} - -# Switch back to the previous branch and exit block -function checkout_previous_branch() { - # If -version was provided we need to come back to root project - cd ${ROOT_FOLDER} - git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" - if [ "$dirty" != "0" ]; then git stash pop; fi - exit 0 -} - -# Assert if properties have been properly passed -function assert_properties() { -echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]" -if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi -if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi -if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi -} - -# Prints the usage -function print_usage() { -cat </` -- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will - switch to gh-pages of that repo and copy the generated docs to `docs//` - -USAGE: - -You can use the following options: - --v|--version - the script will apply the whole procedure for a particular library version --d|--destination - the root of destination folder where the docs should be copied. You have to use the full path. - E.g. point to spring-cloud-static folder. Can't be used with (-c) --b|--build - will run the standard build process after checking out the branch --c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination. - Obviously can't be used with (-d) - -EOF -} - - -# ========================================== -# ____ ____ _____ _____ _____ _______ -# / ____|/ ____| __ \|_ _| __ \__ __| -# | (___ | | | |__) | | | | |__) | | | -# \___ \| | | _ / | | | ___/ | | -# ____) | |____| | \ \ _| |_| | | | -# |_____/ \_____|_| \_\_____|_| |_| -# -# ========================================== - -while [[ $# > 0 ]] -do -key="$1" -case ${key} in - -v|--version) - VERSION="$2" - shift # past argument - ;; - -d|--destination) - DESTINATION="$2" - shift # past argument - ;; - -b|--build) - BUILD="yes" - ;; - -c|--clone) - CLONE="yes" - ;; - -h|--help) - print_usage - exit 0 - ;; - *) - echo "Invalid option: [$1]" - print_usage - exit 1 - ;; -esac -shift # past argument or value -done - -assert_properties -set_default_props -check_if_anything_to_sync -if [[ -z "${VERSION}" ]] ; then - retrieve_current_branch -else - switch_to_tag -fi -build_docs_if_applicable -retrieve_doc_properties -stash_changes -add_docs_from_target -checkout_previous_branch \ No newline at end of file diff --git a/docs/src/main/asciidoc/images/AWS-deploy.png b/docs/src/main/asciidoc/images/AWS-deploy.png deleted file mode 100644 index c840e1396736e81c706e1bcac783b2bee781b6db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 602969 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­MgUgQui)8rD4Z+Kfab65N>#l9mCteq3SFI_D*| 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

5voOCh=mB8RUQqe$O5`Xagy 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

xc*jnzqrSq&oreJHD}7 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μ)>GVqz$~d4<1cx5{+|Y;F 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

h?H6~nCIjMT#tHa0QI8Hk(0VxeUH_c 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

96$Z%RXS-skP;6 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

qf9;R_CtL3AY| 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�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�Tp0By^B5RIy)6}9z zO-FbGxI=h$mz8q)_fvL5^OZg&AEzGhryq8}vaPcjY~+5)ehWuyyl6{V)~~*5Y5$lt zBGoHH(|u@j*JS3jy>xcJFGl&he0St&Vv(NhNz&+Q{6EB<|Ba@?-oPOyn3``Dq<3ZqCfuybcqG%^!y>&JkOq?Q9|I6={)vKaSfoBmXU{nM%|HM>b+1;oSx+^pW?WV$6Z<#0-VetvvE}^C6py=2 z;}cexbh@8i77smfg#2ndui2rAX%S&_J(*dHYfi=PmwuM$bd@-xzZ|4f9M?RE?G)4& zXK=Aw#j;73B^1A3iPEkXMSgI~{&0@z>>}YKv$sEOq6u-sicR^1lxF#LI4n+$_u3hB zO;;Zk?fyt9<<}x%;ZwXH<{fdQFVpZ`d8hWWGJ{g-=qsVPQ{kI|I8)@E;qE`dw3!MI z8(ne#*qhDl++>fWgp1X*(KYXrZM)+GflHS|!zw+WZ{q*giksgyZ6T&kOD{>I&cq2W z<)dk}BvJ)Q15^qowF1Ypbzu)9oj64}$CcE4p?{RwcG4%&3?w~f)8EhSk`C0iV~eW_ z3$4LNgG+c&kZ6MzkV%O7A}1TzodKEn7Xul>zzVAA|F|GpZoIVQU0ouq)H!My20S98ikOOO20fX{;{;{ zO4l&O3!EFUYeQHTXQM)>$70JhxltkY1NcyoANbyn=`Xzuzjcc>e3X0T^#P&bw;3bt z1}}&My%aeV|NQ2p0HC1`HeJoe>F?x%&j+?P;shY#roHv|-u##3l17e|`y?c!OvFyH ziX}YJsr7{lBdS%m0YLMeWkJ~FG-k1tSQ-(Y)h3QMr>ga~+$m{U6~LffhZFoHmbvL9 zzrKpkx-iJY{7&r4or6# z@V_c7QhctGn@lwVVFNI-Oh<6N1?1y=nh7e0brL35Ay(hg^MA#+CLe|t7lIbRM7HkR zs{sL7g6yB%Tpxd{5C#<%{+7XgPcV^W`!UhPPyZ33Ph)qI*8RaAE9gP*Hy(~ZfZFxx zIexT_#~-zbZKfyTG)Yth|BVX@*P|H@=LTh8#eSOx=oGkD)o2wA@hKYX6d7*5DJa%L zSZmmBAJ7G7RMi=T9GbxHWiLd0iXg}yBk#1b>*Zj9+YLMU?M+7~&=pTyYR~Lo8~^OC zA>Gs36qUhVZeSv*evZ1m)xZvM(o0h;_8CSyf@6_vHvx%AGLYRVr+3r@aI`w1h>=l8 zSq)XfBqCHt4qRaRAfTy>!;-5=;PjNM(m*&r1R>q)ig@YJ);`TJ3B6cyZKY-Z^6Aft ztp&j4{d*op3vYznq49jyL{4?zDd9OhWLwW*<*zWs8x6v47<(KYzzv5L_&c|;{*Xxe!`A-5%f#!&}qF45yqT~jfq51sH zU1P->s6B7jDJMYr~&?4L>+OW8fxHUafCe0BYOp)dic32sK}o)wxDVv zFkjUidDr%6jEs2sG4?vthMzSqIF>%v@ylv6JBSGvq0$2AHBmFQ0nB-%d72(YI8k)u z)mGBB+b3sBjSU4?O`5-^i++~M$uu99?7ORPIHDDKa<_Hy%c=1t39UN=rx_-YaIc+7 zG4YhDLzVyWnJ8UaV7^tm4u6=wW^#AS0r3^Rs|l)>DMN!RaAbg>3<~k3ofznTT`oxe zFcRvKCjud|39Xsgmd+CVj4oCDE72SgBR%OfmcRY*Hj(=Fi%}6{Wth&r|Kv2Am77@K z((v-c*hSHCF6$}Z)uqc1>X0&S0x#&_KJI^TsM0{pw$>+h?+Cwqu&Y)3UUjdq$Yh8I z6uMSduH7~PteZFvxfftHzFy}!T(yxU5Z?`C=^?g@3<* z^Roiz*DJRZjr8ZnfYv4spa1#aZBkR=a!_Ewi~zyJBa?W}qr~sP)FTn0Rg0+Li>aOv z;`B&S;{z>KY#{b4SJ*+~jL%2r0pScM_wqJPe!aFSmP`xW%#W*ZQu{Twy-YJ}-->Vl-(2a>n&AS;k7Ok{jAx3$pQ~7qf05?Ou>$C+uPLF4 zF6;zB9pMs=%ye{f+5qKH4M}uS2@fzo|1<;++tW%aiC%2AQhyVoO^7XDw>wZy|2w}@ z`7+B2(|>S%Q7%I~zoGVwZn%26wxF2!OHDLvIhT27igTg3sCZf~6W~ca`jnbsqFADh zQlzwD&NwZzRxkWT)JCKkOMG7}D=L`Cg8Va7yD<6bwAw!GUbRViBBN$%{lCCje-j_s zyx2Tg9sXH)7XWTE`O18W;WcH6_-GxO!{fZK_e%SZ>J@8NuhmG?ilES!&;Lu>a+DDc zgl}}^E~KOZG&e_B;xeSrCy7jeN6$VoEo^Ev2jframawEs&lFWGu!ILnxNL`qdV~$p zgOW=en4Kj6di0@t)6@_+i;cbeY}w!D#?DcEX^^NSIjsFWt^YXxm9|FvG>iu!_Dr!1 z`cfn~Sj`Zt%Kzg*AKkE&$aocS0w-fw&$r_v(a0)l&OD7xR8Yz22W_eaYhGP@uO~{= zm@ubvhuXM@&+mi#|7kpA(@MV@xep?+}1y!~p;0E}_s3O{}1O^#gNMg?I16 zu*5&vkKXBuFOPok<_BtR&MbS%PXXvR?fYM~$Psd8S6`uRY+S+`EQZWku`|X2{3hl~ zUz`F%id8*yd~H2j!~(4Q8N0DvDwM<4rtP&W1K<*s(FJ~1y(Yt$rQm%|3KEdf65n5z zcMS27)2^T>2JL@y` zfFrSHwWzL5y_EWB3$gm3)KjK7F!fw4ma}fKsfeuDCV%U%UGTm;RLH1tRxtiKv^5lp zX|9omjyv~OmGw&2G~;e0GHdUQQLveudv-k~qu;z79SVie%YXb^Q|y1~2j>rbH8_AG z%A$gS~`tGwhJjjB>)yjp`kFbR{&pVsaD)Vl1>&7>@*5V ziHRdcr&S^N;Hmc6pqpWJX8hAY^fQs|R@6+wkPPS-;mn`{7{EF)i^rNg4!p@b93A;& z&_8|0^mkL&H=IUzd{)A55%Mz=ZDO_=V#XAInL!jwtb1QG8+ZZn1-k-U{c&2C3Lx)n zhVXD$+-7B$vHtU{^lx0+rNOhfrx5{X7K1Z15r21zM`m6ZojSDucowjDpPCrrp3H&` zN=nE%lUA=*pa ze*x$1hl5akdn3n{Zb2kRpRK_Ypx~)fp@66{j|)wNVOG*|2TStj0>Q30*dYoa`U`YM z4w4Knud>mPh}EcWFWwhZ@@-QLV=R>wnAOXlI)*`UXXv&$d5K&Z1w4DdG2%Je)2)wN`}(iEAZ){PA|}Vsi-5+ zAbKpW`<4A@Uz9v`nP1lk26W}WL8G~IC?g~VaTV-;^U+KhV2Jz3I$&DRRYEp)jY*IQ z*?+*SS&konnOJ9n@l!sg^7WGTv3YvFU9=jA^!6hR)L{j@Wjzl+-cj$+4kD}m-t8qn zN128Lx(C-&!+TwYvcG=pC(!=(tAAdvF`!V}<`ujWrYMosaIvEx{8B~RpzGgKH*T)Q zSX+r2+3_6D$`wt$yhfMAIJi_?3@(@J((5^dMZ}6Tx#6|lKj7P&I8%P7_;>#Q9c>tB zjteQwV{$4Ixe-7W<#0OcAz}l<6f@M2TYT_sl0fp*Cg^Kdfm@s7(c@up z7#{PN=zpOYH7-@KvK)O&Vwgz2^XkjaMeDXS?XPO|pEvz?OH5KBanjFLrwE{jp^~J; z;J4|b*173ZryKf%Peb?F!loJw4%5$4Kx0I9%m@7FF5PDo6#^KZZFn*B(sIks>ExhD zl@t7v2V37o~>kR(@9oG|@lSCl|xo}jFYZy>yl zzf!D#E9|G&n?@SvKRhv2G13eiU(iQ%EG0e`8{pz^`6xpVNF<8;k3jI}KVqSYh2fvT zLr1H4^vH*+YIJ)?V#FOOH0tqvISa&sl!DEv5=t`&#b0lC6Z-bHpzH;M(wIetKkU#Y zxodkQD=A>w#MbCaySV<-(-aT+eo@tNsM1>JDy&M}2V;;c?35B^z zOmqj65t-^dYdwAytgUPMV$Xm5>#{?)aofuucX2|k@tGHn_iUfSH+K?B!U--(u3(1lU0@v?y@HsHgOEHYsxmu+L8KJi>4efw1t zms{=sO%L8Qc-UN0H7ECa_uZ01q$bkrW*Gpnl1RwY?|+lW__~b};!EF+j-(4>j?9Le zuYk`17{c@_^=~cWwv?a1c=YN=+1t<+p!&aa*e{3k)fE$_$ID)lq9N&qhKOebag1f; zrON=j3ZsKV)NtB#DvQ?GUijJ}d-K*D!NT=3#-Pk?xx+4YN8g}I@icJ2v}h!sZ7yfL z-8Z~mMSfPjuoI;%QTt!hTu51&rk&GY0;{#SkN=nCL6C zg0?Fy9ps)ec(|3SVDsh=p6YX6^xFDizFhE^>A89Eo zbEl9J_jX)V`M*z|>mTCdp=7>JZ#9>r)HSB)CALt{6?RXS2_cMxu9Fc&(xm|`ILN|f zLaZ5zgmbf{4qlA)gG^7Hq-Y#%yoiRn}KbkD{ldyGb2}mq}emYWGY{j~k*_ z9{vNh{}+#TqLEo?gS9XMTJ8@>Cxd65}1SYuRyesC)*Rv45q{wavFyfSrG zy+|ZC|8bclDp|OOk#;2pxi2&yv+{UKK=o0Ta=RkGDxG3B;e(jqk9k=9$nQcn+A)Wo z)SJzk@EM;LUVN#zl>~iR06};CpC;}GJfm@I`#=Bq%F-fLiQqh4SocHmMHy$yR+7TJ5PtIlVRvj) zsAJ+d*|;fh!bI#7ZA8HNv?1FDBiBW(k~Uqw?8aWCBn214wMWTl2FEqtbidErkrR99W|p zq$CFhB{uc|5^2d?DzW=X*%8zDR~^wQEF|<$#I4Zo`SuTra`%a%Oe*B_#ZAG!ePE6u z!Zn{C_ojHF^`>~>ecnK7PnpImnPs2s5B*3 z0=_UlbF)fbVn*aIaw9>C`R)@})5fn(t}(7DV@ouApNPKwR`Gs*S5v+7mop1WQfcS} zqo2-(jh8g|*m`1~`w7@o>mX}D0ZB?;t+uHL)KeHX{H%XgXKC*MPoHTAD-i*iv9LD zy)UbW1}C^TqWIprkGOuO>EC4VJq=#;8t=(cKj%V9Ba}7)eVXTe8X z?FpK$+Zj>A(LwXHK;qUGQyB8JWd7}%J6>)>DBH00ypQwVH+OJ&k0c%3nt9G8U!Lz> z2^_1q{`(MwK$0-iBN1hjK-wlXz{x$kCSnv=voY3XyEK5Q>O1Ht~lJKs*SICoo=;;?8UOuU`jO+MB24s3244X3x)tnf)sUXJ>obg~W# zxHp2UPu`kyST?P1xN>lD!FZDE>f9=1o6lbS9lDQDQD68DM5hFY4JULa5+LWWFk?Of zOC{Q-qOJ;JMQ1By11RFZO;r{v(RoiurG#(Tm`RU40+^E+Q-jCMGs7Q^G7S;i!T2n4 zmX@W-ZCHK2DF0M8Q$+Qn(WeAfmFjL}R{9g))2FyiJ9;Gc;lnk*3m}*5aDK;CmuJs8 zL@t?b<%*^|iBVp3MTRSq|CX7f9ZQoKoE*n>`|r!dx0Cww_xpdRPxaj=xyG5>dKqNW zZp!nb{#PUN7BYRq=}SG%?s*)nn~`tnmo%QV`Jc{*Kk>(~Dcz1Wx83!`eM6J`anifl z)3yz{V1jpP=Ink_osF5-YRtbX=D&a!8y{~mT){ILlSZwDwb%)}H?Bvi9H7toN*~Od zF5AxnWeNW9=>>;68a^-z4*;vvPkg?JZ>aq>EQc`Y5B{uGkLKxb$ESXGgN>#f26;2S zva3C*5ZGa6Ae%A(LAE^6fWxGMAf-TY6Kr!#iRUl4i7vwWMZNd}r5bl32VuV(Z)v*( zL&5Ru3ob>P(ZNm1x|Y0VC9(VO#J*XKNu>b?PU5PGXVpvq3Zg{`CS;xE`7skFPh1t?Gke<}tr9;AKwg_|Hc78s!F z9XcZ8TVeai6R9T>yb-$j!@;Hj)%T+b-XUS;gRZu=0-LXC{$4opT5j|2S{VOy<~0H| z7M`29Nv92#fvOpg(c@2yiopXfFVrPI2^e+6xtuoM2nQlS>=u}2L`Kdr2L}gxmkxuD zV*!YNq!}Nyb6(%l8vTp*z~Wa)CFCKTtbX3{A*CeL8oHsMvM7k&@wQOkePlr`_Vlxy zW-Z@$nPPQpKTO@SmAVGe(w!=Jc}c0g}S@fAA4y@zBY@LOYBDOhkBpc2W%!Na69L9 zOYJyEYJZ?z*ea8ZP7<_CT4IxgOJ(BMc4q8M{qC0Usi>+x;pTSsf2vlb6|PyanpR$p zPraNqgxvX(M){dPI^W8&)O^^GNw=JEN>h`Ry$*A+BRsHod7}@xnZgk!nj@kFOzH;WnXa+)x2-j3U#Un@=Bsf%-B>#-n@}J2?4=O;&ebD zvkfI>mUgQC8^K4Ii7 zKa}R;_#s>0R+gq#>AW>w0N4K<7Oc7^V9|=^u+>&(;OdG_%%UBz5QR@jOl-KC3|+Hr zpoqm}XkTC{UbLp5Bnc<8=m7EZ@~$NP_&3eHC6*p9+D7h6{yh%KA2!kfU|xN0CQT~C zw?si40m;$!Sv4Q{WJG*JN44vC`m@4S0MJN)VGa&ikHR;cye7q`EG)iWX3Wft?DNZa zvB`WqPv&~hCO)}*ENUKIhqc*2$j@OGr&)?VPJN^?cH5I|Mt#mY?ucwAfn-b@;M9m^(8Cq!mZRbTdl))l*?7oAW-E9fi(_S-m~hah?g;h9QVYZ5q%wwzAh3LRnhm4xU^UIt;LHzJ9## z@N$1rG<)Veb#(BOR`BeIUHNJ}O#b;B!QAS&;#w%*+|4&p`pRk;@2NTo%)Cy24wvV$ z%cvj2b9S%$-7eV^r%;LVgZ`T)&h5(UHiC%utJAqaG1HQ!16=L>i-P^DQ=!Vqsx&If zLBT6R=$vaO@o`-`aJO0T)cJC!rvPD1{=((?PV=tZVN_nfgc_1ER8rwVa=(t`P>SrQ zK9)e%zmL^S?Aw?2k&Pe!t^^)*7MqJ`el5pVqQ7$08af)j_^`AX6F8@O&I@Bz$F@up zxdsEnZY=U0BC$_NXlHt{?CKPO!TR#1u;MCHd7v#$&oexg@`U~Jdk>@SA#?TO{BF~( zb@lzYn-e8!O!zU0uE#@Mq4OH{h>^O^)F08^S`(SYlYCyJ>U*Nvjw|F={*D?vqeFFntiVq+WyBz6x;rP6iL zCK*~G3`HVL#t*M@r`~dNt3Kck`5@@lU>BuKZ;gGN%w?U4Nqn$G@mxG*7HZ@s`FcB? zeOr0dZr-l*8WpbRTy-XB0jKxM+1#p@b=T9$2f&f5xXe1*f{)!^Qe;4^H#Sb2OPbE_ zHuLPzIMfUZdQl#dFtznpUk{%(S-dadKJnl>_42hPG&z2?`h0bV?GZ-Ap!3Av*q5*1 zYvDfghImanv+zV3fM@HA@0ChP71Bd#3)Xf6T#??!eT%HRZxx)VH&&S0dAl!Il zfylqRTUf*&qUeebY!Vn*r3wusY&R5^z8`jbNJMh?3e)?T6P_qr(tHN3_uJymoRfP^ z>6EF%AuTZPk0V$pp4^x&ax97~L}t@)VjucpvF@r`{SsyH=1ROi&rY=3`|cRFT>DO{ z_c=;O_{S;L+tj&@7Zm?)`s{SZhx5RjNt;q6iW}?9eJi3HJ|FHFFWW_OxUFyW>)a7! zeI;B%`+@Yz40%-2w(dK*r0u79(N6B`$Q3xgE5}*&yS0=TI~62QgcAd@$Q<7J#9}wE z&=q1CqX8#;9~7gJvs^vz3SXKyuG0nXOw`{P>)D}OncGz4HLor7?rpd-S5C_3BurftaJG|Cv13+w4zWvVhduex|Z7`;k zvdlFuD|6gUFP24cp*JjZWGswXrt@3jiVdO;yb_|t^t9-mI`E-9*{6s+Y6q=KskIRC zzabD2no3-h(({(38H#KX>IRI7qF8g`V1O@ikMUTbxfaN`CI3ygUfMzh>xZPcx0S<- zA9x|@GLl5TFp0ZSPT_akB=;H@P7Z01*@Mg1$LzN1Sxp^$zN2+IcY_B>@=6{}o|tz- zP?+lIM5cOd8EnB2DvK~xrq3~yE_=ho3m~)C&t4v{nmt15j^cV}7xS%~#|euw^qptD z72fQWpKnesLwPO=M+uz4)eU)9>-XPWWpa@!mIE7=7icerIG+vOIiV1ElD_***YdY5G64sjzmf*UdYtWZbcvt6dU_51tbbbG~mJYkre*UNu=T^R;air!Jgrro!8`$9lAEcGVtx_42@@VxAMO z^WMnIF6Pnu9k=8Bz@7QI8f6XjES&seT*FTPX0DSka)SbXuY&rH2=``+7EqGU|SSNP_n6P`#lyx zhtXwC*-BzO*TmB|Wb10tUP4y#ABqrs7hq+C<;ZS|rAU?(cG_dFJzaAZ1`2L3`e9p} z#w)qi`W%a~Zf~yRi&Tk)aVy^SfJHVr9+#JpFbej%=-2a=rXR2IyiRh7su-x-{pTrF z0xWDa=N$>$1?_UaxNI0RG91WLUX$sC=<~D9o?PS4oHVH(PGTwBZj3!qC_7E2WNP2u z<$itfW@h#CBHdz`&byw|sWz=xWHkMLtZB~pLs(hs)SaImg>JD*_!A*#6dpMb=vs^4 z*W$np?^OqCe2=@lliz%XlG0}!OvrKX;bQfxj!CI56%25EWdffIDSh6_03~_~C)S6S zyO=I17rm*^O)hl$-hr??J-(wix2E~t>4&ghjpEO3^dJ=re}U7P*>yRLz0dWEES!6v}v$8SIZ>WD|>oG;!%;jedetuZL%l))#C*t}Vd5W7>(v1&F zAkVJ)Dv#gRf(h-4hYk=rMnawNVuZa<=_a1TF5Ol0n@T0a+UskibKRF9A*z}NJ}Hpr zn*$hchJKvz+wyKY$gg<+c5LVAx*f;*8A3`=cXHJlzPz$RW>*uEGaj!cw6)nw!tZ%? zeA6cYKOU76z=BjG=9ZX_#bwi}MB4A;&N#;%9VY`21<^lFg)W0AVDkf889VmS^7hHP zVph$uvWv*hl;^-pY~BwDPg^O}t6*W|!S)+%QYI&ry$aOLBpF{wkCv~3Mh7}-4q4uD z^OJa3!Bf3}E=9j-&d@2Q2aQo@l@&bxerU*@@dF~peWWOBOLq`KDTE_*(d=J;)q2AS zaC5XTO?KRJ+;~RM=eI?~s2(pH7>GWUL<+F@QTiF&p#>F6*1X;>k>@uu0N;%I<2(m$ z)gG=S&Zc@SL=sbecAmDtFt80`$5L~h^4l`IIp;Qe;Jho~%yazseW%QjDgY+uq4xPS zaUSC2f_A zjGWQA-NC_^RwVn?W;a`6;uCfmUc2slP4#7m#X@$-^0zc^{^ol3L+XO>#jXU5^bNRQ zWu6eC9#*t^)Y`{cv(N&RdGyIw_~~@sXv20RZOx`AqmrXL|K)iWZ0AZ&dK)x|tMFc?sPe=un}?H(A`h@ZF@1VMzcg#4~iz* zk8}6rq?qY-_@ml6+&P93SaO$YfC5s>!pw&k>TF`7$O$ZGLiK7KmtW!|^1E7~6<){3 z+*+9Bdftc3IeB$%&Rlu=S4X3AUyiwFtf87rr-Q`Cn-5%N&kei4Z$96cFuvHn&9>*0_XAYB%$6&sbyU^2!&z zB=TSWkhY6ovpR<{;ckcVxRi3IZjsBbd&5h8_2gV8snF68P;%N==lyjokN+#NaW(t` zhu?ZNY%zT}Xw>**t5(i6wGrVZe6#M0!9$Q57kWqBJvuNM=dWV)SI@{iPMBjdKmzNl zPPKW{QZ2A0#ovv(Ro6GDSu-FxDK+BAZjlzPx~3sGh)RH^^#q&rL7bSO3D6fCFl62Y zy%%p218$CYT1I3`)Q;~aCmhwMl5sn!Pmk?-^Y1o{s*xBWm`<2_IFUpztgAz>Nh|Q3 z5Mvp)fs|_oz4dC;W$#8CAQXVam*fpdgb znAjIY6p;}#iOJe-oyDeVkAMA&D(1ovxWB z->I&@s2F?|*FCq?Hr}r$C@R*M>Mi*7=ww1Xuk$SNSY?%>dP_bV;dkvQtPpZ9FeuF;%qv#7pm?eLwf2Ys!XR*=rLJGlP* zoJFjYZG6xkp{i?pJ@le?mCk17#IfE@c)1fHz6w!4d_A2RP}3nD$5juxLKffC zjymei;?P!Lc-Ofb$mRBjzZ`IY@ht4)=E^NX2kn`+O@|w@?yoeN3 zdo&}H3l7fb(-HxP;_=fq<4GkN*jwbtrG#_wBN3+Y{y8()bG=iu!fs>Tti+~*&EmYX z_ogk1wpT$-?JkjFLHFoP?cqfI;9IUr?(F2|mhzvjN&(4+j z&1U1~NM^LDFQv<2jhkK8D%`M3u8PG{rbj$YQ(+rLyjjeof*zN~4+hEuL~$QgVB>gh zd7HXxdg3`uj2Y!)w)}o)?KXj@3E>T4WrR)(!vS{YA%XWDksQVLe)&?{n|F zzBic9vRMr|K7Qn!cWCUeX}*FqURh3ZI+>aQeXr%HM%Fre)NdjJPv^q)12N6TxT6K# zFzM!PDG!|IM3YoJt|$N{KYP7D4S@@AS*(itY!J`s`D2)#XFY~p=IoezuGJ*&a$4pw zC(&h&4r;K`QA7u*&f(RoSM{Eye;++SnvzP6ideL?ZX{r&n22O++EwVy^{W6BX}n@^ zIa&9`^pf8L^=j0$kh-(_A(?2 z8wzVkb>G7QEUB&?76;B5NSYUM)~+b=p$L9nqOQm8w}n&%dbR8BWvD)#8&^>@2z)tu zh1|Dp36*bnecLwC_MRQz+=exN_`V75!=@Q}jfG6KrAv7j3YUEum~f8nUUw?19x<8P zbrjdMB-A)K;&n+qGbDDW{qgb(`hge9U3f+f7D<1x}Xu zd-qp}I*mZfGw_b=0K(N7`L;)x11wmn(l&y2K)3Rb&l?hBeMzASyDL3tQ{2YdTn{y) zorNdbz~QkHv(*9?>sMiqS>upUzzuj#-F9}Lm}m8+eH*6o$(hHb>4;cgGB;(#YFBTr zK3;csa^kZjo;4fm2l}^2eM7FiwsXz3@~F-zl|cUG0A_hr34Gp#To7P^SYOMCC=H#h z>+9|PTGsg}JnrUq2T-p_{Q95lHK4Fwi+mjS79-@o?n#K$k-KWY8L zsgs4ZWOB)UZrs7p9e<4zt<5znFCX=AH$H;1q}fl>6H{uAW@)#IK3k@q+~TXm|L}Dc zP*HAOTM?y2O6f)#1f*NKySuwPh7hEryOHkh7U`DmZWy}zfAM}d|GVy5vu2GhojLD0 zJD&aQI3p_AQ}g1fWWSf4e9w6U{7N+-Q=ob0Qwx^6Eq~n(XfyYbh9$pOo_hrzwOkFx z(bvkQdL_?az(&MQ(!1NXzW4$6_relMWT1Q%I=VRO=d_(P!zI-Cz{6_?!VXJy4L@aJ zg=rwu^|fjwvl#JSH(rN-TCaq8lCy+E%i|E6e7MS4J9eW{Rcz zio6#2a2n<)#ITmuU2C zZq8y#U&He*FjrbbPS0vK&%o(&Y9{K)Inn4tsYY!{Wn*#e0+1XU1Up$At$w9t6`#N; zDJwH0$X?K3sg;xD8ez>XEJ-!wA5*pYaoo*zzK?chl<8nKk5Eo_SE#hyT}a!ptE9=KYaTcJg+K`V%f6Kxs!99TtFj)vx4)A@ z-X46~Jr5-d(Ahqdnpxf)oJ1?pPU1$LE{@Fna)k&z;2CZ!~IQ`4#D&KK_--x z`&9Q`liY!Sl4-Y)A4PSl-Fvi-`|OnOrc;!imn4*LdN`FYFWipeqJ!ofB7J}02DJ%c z`;ENQ@IH>y@V9xV5g0+5=JT2J;tP-lY$>(Cqc&sb{Z>>oZ&E#HDVI{A0sTcS$Z`KB zL}PPv^HcXs;=}#Ht#XyKNKy%egoMTJY@spd;^t**O?1~=CaFl8Ld4ZMw85nxOUVoL zC-yR$c5^kH<$np2ZkV61B~$Cs;`r<+i+Ag@F^$nBhECWIT&-n!Pq8;RPRo;4kG&5d=~jtS~~nNc@Cx?mEU9e4Jb6+$&3^)dFGF zbj@_Zy=~NmFk^yBo0XHZI%`()(Trk~>*gJ)c2_X%$nuEhtDTXPr}tAuNFUNH~&Tt$S_plRi zeBL>hn+6IM!UaJ%E!nk>g}y}IriC2;l5M%d;r=*RDgAKV9q@_}$Txl1Ejs;hJGwmsZ_5<&S{wKIuEFQCi^fS~mvt;o}xxH=P=#9|F$q_v_{Mu%k`2Lx6kJ z9-OUye>1#zdp|z2nDV8ge3Jdq<6UX-XLof*=MZ|lY-23Apw{Ix^ zdgbvLnLEzsGp$@S;4TfJ+4b2Z;5fr=h0X#jAN-JgM|K$}QZuFHy44To=w zoDW#X-MJBwJfX>7R7#gUYLeYdd_jLqGC_AbRzL@Jy+p5DA`r%+$EFE$GSh?zTM&Xq zMGLVnSwEz`YsYA%rlet7t9eSjR5mxl8l^Zi0OK56Sr&scl}gmV0CxbbNl87v^uGgJ z8@cU$T4f&Ddbs#}&6Kxf&v<;RWv2R_00mAuegs?PW||x155-O1hV!TrbgE_UNVWu$ ze_ewSJyP@HS4;oz#g0`3-}LBkqIRamyN%ft$LNwm7wqA4^;mJncBUn}o!KVG=+Z*( z?cwwEcyUmE72N<&zkCe{#=!A8(N*U=ji0OPj!PCw^ES8Co1I>kbq{_?5|$&zoRnLA z{^y=eXRttmRi8@}4`f~`X17WccXtDU?XZ5M^=#VW7tjoieM&mi@v71CKh-1|PiEn@ z#R(fXhKM{m^+*jqP{>bZL0o|@XA1i@_SqcX<>H|^0_hDCNxU@oE1LI`=C37UqoW}a z{Fy9nBqWmn`n8wbNxtsU+dsYD!SrxTz^Et9wNJ$Pz{->Pv)5PJ=B9H?LygYmKw7I= ziw;rbZ9d41RePE9g{gSXec6vxv%Y| z_q%sm>^R$3SHWY&A~lj5Zz;&4xECE6Xd14VHv=x`Z=ZbxGLVg%1s4S>LVp4yK>)R=Q@3lmO;c>#8B*gwDjuZa&6>`2s zUOzNJ+jd3jHUE9Zm%J2aIL6fg4I;gkS9H+`Mfs6;NEC+de()oln>`Fpp`q6~;D9O} zq7}(whvPi+Uv<1mlHaGxQ!fhv+ta$lV`w;s(Qs3KU882{8)S?!7C$23{7`RX-FDsj zabjmDRxWNqP^0+q^dJcb)=J^1d8y@gy3xK4eDI)(S9E^8cL8M8;cDkOG`>oX#*w;# zTaIZZ+_~^1+0XTJTN#Gm(B*Wm6*<*>BlK>)yB6ubo?WzRw8-s&ORc#)1{nRCr1*^$ zZtkK^S2xPbCAW7^)o~U~CR&G0*QRjH4vixVPK$osxGvwD^egs|<95eECxP9hisj-E zpu{IGqZ+R%1doOr3gIh%FwS##AG;45o40hUR}AD`2V+iY@BTR99BKa1mp4Z!y++pcbwlYlfUdVMR~IXm}lZ@03o)W+IvweIhH ze(;tuwfU5bj$NNAWNV}57St!%aK1L*4(;uQIA*O)XrtQ(^nkpqvzacK@oU`|Jg@~9eZ-zN?e z(6ji~iEUQ=Wvy?y6|IZvM6IUOeD}WPL1w1o1y}dM2k6HZZHk~1xqS+w{GsV3jcXKh z?r1-b*Qjs*%xq{A!EE!Z{?8k)(KZeRAKMq@-eBR}?x0I|e`b3>UY;I`Do)ZxV0AMN3F9FS=vldaT=w4Jt8kwdKhS>hv?^ zST)nKwQD9cEDX{LA>WQNMdg6?3*_H`N}Iw>Xcs`k_jPL}Zi6|@T92gmlWux?M6ooK zOjF#JU}a)h$k{!jqG;_ozcMLgGI^4_LxuU;#v($O@AV{K|Y>tBD<}j?!;;{I^7QIU@Z1m zY&uS2Spany9UG%_^o^I$_CQ4vRzX2QxuI&BC17h^Uynxz7@{GVUb%Kl-4@pU85TTL3Mnv<%P!Ez2_)JD` zMa0U?uu^3xEG3c$!dse*cu6R(kGWD7Nd&RG2Z?Ce7NfPuS1~D9SzY~e!;LFL=m8iQ zINZi`g*ADL6Az&FR;9h&#Im{p#L~Gh$1g_1qh=jXoNnDJVt*$x0ioB{gMK1_rJK+v zcH{3e`9&hj(>+aK2%p=CL`MTWW6{1N|G`irky4kR3QDbjsAbExV!rugq95D&jfWPH<8J%aqz~6&TeZ->{ORX= zr7e&S>1MPfHI*-C_N(=9fYfz2qfs&3|{~OA-?mXLuuAiIC&7mi}Ta1z%`W~o} z&36eP=@U?XUIxTkU2j=$06d93wFdw;ovD1_{>rrzeBz(9FnR1^2CSP)j0k3n?r0Hy zAJltAdY0U*#9Iy|vk=hYuFhFzF2yvP{`0zvZ7&{iLfco9#e&s!sR|EPuYiVofYpvA zoJD0^`U&DY32$zv>50knt)Dw2^h1wY9_-usCiJVF?vI+;Umv#NAnhS6XTw+CZynyC zj300!PH^8LDloM24_-dtRiV%|v9q!Z&Jeg!}rI2suvd_gMh6ZO5d^ zuvQiCNJ#oq4jzwg`%T0Se`(pc|_Mt6zLj^k%YgEk4KtXaH_7*`oR8%0ES0e1tq^$Mk@u!& z#QIkDmJC7j?eC%b?+7uRM+nkh*YaU#^)sgn6zaqJvxM=&AK+5y^L_X$F~v;F3*C=Y z>Yq;@Jp!5*E(9M++z6cfHOL1Jpedf_#MvhRo1q~%d5$w#qA~R;nA6Z6DHXISQpcPr zX894h4FF53$zUs*Ms$Ci8&B%pI$&tnPfp-6GS3pr5%qzF1LOo1W~dvP?etpKC5H8c9g;X4@Vh}>{~(rsX&ajiv)K=Q0M~eZUbqy9fv#knm5mWU zvrtz3d~@AttSqbBmFVIIHkw^O_<+{(+=qXPuiN|q5_oiTOz*7tEQ!6(ZdL)``(g@@ z+QTZ#EH%h4=JlAxlUa258qH5Gq{(~}mOx=I;ocH(b0gmFH!=hDm(0^vKxHBY1%-Gc z5|JMfV~iy-mT%Xq`&1tJhgOB5I|#cRjrWLFlyAO11JZC^_ZO=0+`IbD^z^r!L=b;7 z!haWVd>~n3TtFre;~Q7<2FbA#9!Zy$Mo|9CG;-hvy*uUg!Ac(raa|cqABR z$mqF0v&n$ze1Z&VC?7`RM5n&FPKvL^Y8-Fm=4sVU2f12h(1v_^NWCQh=41eR_Bs0Q z`F%1vZEG#kKgM5aks=Yz%IR$^hcfAL^>%Z?77fCT@_EAQDpvGY zi<|}T=eOAKPNu4*t%90=KihwtIRGBh8!*QQ?w=c^d3v2lJ?eq5t%5Lxz`@6Q1OCVE zFyz1t?o*p&ym!o7``Sx?gpvRI03>7sjEW^86m=XsmC_Odzn{a!;qL}>c4ug(`AFAI z@%Ahlx;Zmc-r&B_lu087nlFbNih&s@|LeWl7JwuS@u2eDp;f+H-iKDaG4MkQ=Q3o; znRn*4b(%*jS&!DVXXH@$ohA9lq5S&ebOj`##Pf0L)UYQ_st8*W7%aj=GJ)=IoFL8$ zqehOaxDTOp9I9b&SHh<;K-IOH!Rp8agzRq{!J|cl{{zfZ4_n##rNKaH;7T}yftv3l z(0#Dr1KzLUTWRtCwoD3zZwKbDlXC}!JS)u&dm1lov>^SfC1-gC__{M>2pt=9;PSl% z<%e2sBA`2q7!k0bHPaV zs4@6K-)#NDgvcNNk@PkxY^k0d46C)m16y7T-d`E{6R!PF%nnhcbsT5dBh zOJU2jDj~{{!b4(wL*twuj=cC}%DP(~hZkMG3(2_K+-3VOx`}O1_M%$U@ zDbMu6cN9QEZF~^mMJ0!&$bcY(h7BNVcKUQk0%P)cEfGJsX&X0B61N_Cx40DrJ^+KG z4~Gu+=Rl{a>y%m|cX#)8+$a|xgpj}S)>x%5Vd~#bUTd2HOLb52daYxtUL)?T7)ljy z!HTuP**jVJ;_J;aNPY{3T1h-; zY5bGFKaB?nrB|thklQ);TQ}tYml`YNpD2Eac+qm6rO|7iRFQI?G*Nl&xejR8h0zg_ z)RwXI7FH3uN*c7h0zs~orm+GLngl#P=B3(assw$xl)r_t-*F(Ep&RY3)688T=+G+k zvpa-3#duntkvj=7=ihHD!_dfx3Jk0Vvp6Z!|D*KzuV>A(NErSGi}KwCI6PDAUEhe- zW`Dgz(mDI&_a6kZRV(L89AVXwcQNf4-XE+G5H9`-#D1N0MaVM_t*ugNl~4WAQ5gs& zQ79C$QK9Qq7gqIEmwDJ6C)uM~Qz8jTR&n&jY@%&Pn5*xEqx#L+b&BF4-IJdkzUK1y zJk0^@(Gq_6n|GvJH5SnbdU&yRST(|*#6Lr#!bg_1AqrP}BZ^3;6T&C$VC4oC|A&P< zqJxMVPL7l_dyH)79*jZhkL%f3+v?<=mV#x@BhQ|*j~u18iv3Z&O9_R34Jz6&fBpZ| zfJYO584sQKW#Q!bNMg`3@B}xUy1l3+f zeusE@ii>&?{}*Wco9_JOeH7RfJkocU2a!ZyJ)?=>Hv6sz=ZG~~8==Y7_(hqlC=KS8 z-glNX%6tln6VD_*_#4muo9ucIka`9F=!}j7-^CQd!dHgf-83gEHz{X?CC3mg4aa?L ztPz<}YY?5ONy+9>W;{Mc?70&xe+BdbVDovsnql3PFHZ*^XNDJ_hE0@P-2!9~&5y%L z6p0^M>TZ+I;P^S(a#7R8yf+SKQ1?%M@1GVLaK+1Gkh-)Q(F}W2ed*T>8&_6vBsbfv zFwh9$x>J*J^f(9M^nH|$-W0oQ4$rtXZ_fht*Zyf$@DY)}cdXDCvzwI8d@*GXCxUB@ zvcqEPnR%=c9giTlwHcPow|0{vcU9nn8PEd$weHiUb;(G8{xeXB|GN1}0H5Y05}b6M z08TtfROiAW_wXQmX{s1;Ln|H&s9fnMQ@`-PwB-EFJpZOQUN5}!)`T{$P6TYX8!;%V zPF2rK7$sdgX(+PQoWgDUqLgLMJs9((b^J5y{_WzD7QSaF0dR`Nkiun;CQAR7$^z6PX$@Up!;55vMcznR-e8WM&6S*hwfa@75 z?(bo2mkaZe-3}_Q@*52z%t~Wl4NFCSnlR1Z$Jestn)?rE$pfJxg-^gsb1+AZ1h*;N z(NwzeW9Y@MMnM{COG9k*p1YE+u#t1;#pUo#O}XIzw_(V_P|wB5XeP2^)=Q;DV11S1 z+PQ~fPm^l0Jpb4*}8FyvUQ<1_&BIwuyoEpfde3! zJfQ?$fn5fw4&m+wePYJ-u(t9N!l6Md#qd=|eH&w>S+<7+vUjtBeb;)zp*tv8K<;^& z6F7_uT(MXHH;4Pc5O;L;)l*~Xw@)M4T8=4-1c-!teda~x(yx=pIr;{PMw8*X73bsD zlk;DrD7-FVIs`N$qs$b07I*M^^3f=XX(%LNCkqHS4!4Om*cS<2Qus6IS6-G^^8Y`n z@-`>*g6S5(QYQsGpNR0z3G(p*e0>=x4g2=oD6rX{clCC$G?V}3dViV(wSM)JSrPzj z)QmvtIl%B=!FylD_uJZ@<5ld`3vG-pLW=~Tz|cf!nQ~nx%WuzXK)|7%CDc?9{EKn= zBQRg4gwzfOxo^nM++H`@x}Ia6TQc$nsmlpbTw)R$%-TnWBWJs3=bQg=Kfzy|sdJcD zS{iDetOCW-gc4wp!|$~`DYho9BBJ_Z#oXniJGwiB^WPWy3eGI@4Mhs$lfHpYu0GmI z{wZ1Wt5S>J-;2KM_1&cu%#CB>RZ7UH12O6_?babCRUw~P0F_n*>v@Iz)21ECKnTF0 zMJBH3$Y#5{;8_qP0a^HPIcRVg3)S4kK?K9r&{p*O%DCyhlB^j)V%JD{TB!6MGBcW?E0zS z>C`WpjCzA@p1}JHY=6rRUT*@U*~Yk5AqfGOCIGv#)+PGL*gvKnI(kt9R`-a)+v@;y z%e6IutODFg3|N6T5FR5k$W>rcnAFGWtCZHFABI81(UdeJAb&CU!5cz~4(MMf=LFL` zuRm_%=ZKyxnWqPNMsOwh)8U2VLR>jFo8G$uV@QUTe+`rQL#2B7A;$F>kSr+#y0tov@bKe@#_k2)E=6?S3+#?PdK!jKPvIC3@#Z|n%)^11?a|aV zvKyV^9mIW>aeHBQ+f}b@nW;qeAQV9;3Sjb^M6~Bpn=3r#nA$4noAtK_dB1B$dA)=F z&cL)@pjw@!=!~xTYd`*w-f(irylz9-NqIPlfUqbAtf}4>TJFd(&*IN%aO63`h z#3WYcyu(`gqid2{q+V{Y>!#VmghAMU$&Uc$mHz9q^O*s{B+iXj>;0uoI<@jc_~|5t z!m@p0O!k|gbUYDl@6WQ}M6Bp;uou__+YDf%dgvjlSO)0Fivoaawn?FhiG|0Hi7GZG zWNgpkz92i1E8h9sXUosk$U2P|23C$XIeOG%)2bvS)r~Bt?%tAG?Nb zCSZP_Lbl#76ZW6mQ`xPgy| z4B5e$6AMrgXF~SEWB-3&qVMa))ThX1JKqV{C$dh=TC3wfnan%#Wm4sW=2%wdQfY@sKc7=)^0RA>l_Jmtp{{Ud#{3 z{uiM0$HIANh~Kh$*e(UzDj7S7>Rgb1WFh>pI(r?zNB$|eP}br52TVQE^i|CN+FBM8YsY?9*1LA|`l{P+kZ)f{RNyoU z&p6hKT92$so-+JV5c?O5eM0ekyYFX0Iy;}g9}PkZW&R~0 z9zUDU_<{Mv1Bhw@h&#Tn7b?qQHa&RD*A=sK)>=pZ=k{SjW=P@2>9tZvkC`d%BzIyh z5pP)Syua>O5?>SkSIpid@{Ena-e~*ho9*$R#p!x-fKJ+yKF8GG8anOM1iU{PM0p%d zU#iJr|K?U&_k4rlz1vdc2bQ2^qWusHU3-p`rBU$`|x~nZ%Te}s>Xi2 z2Yl-rqU-iPazrgB(UsZri3kr9?7@Y9@sr_7FjpoE7;GQyO`cXJ_1GxL8ZD1Y^6Mx= z0lBkVAUE&_R?7p#$R;yvHcbG|_UlLvL~iBbCZEhpS7$dVKsEa*edpr?6ZBu9k1#$0 z#0Y6ks0Xz<7!$*75?Mc$d z8;x&fzxEFAY42L>`fww77T<@5|vG|`jCkb-MQj<1!vMBtjA4c|@YhASQsOm{f;qvClz`x;cm!xO*#@nMm^V8M% zy8TKd0FI#t^kiLbhsfRdAzWgg{cusAuH<_F+2>Dw=1Vwq>J(taQ(lYtr5qTpl zEpvDG;)Dv%@z=$h|9tY_H-dxUjoV67^2||~`h2(}_|v~t zLj0!TJc}gX{<<`Tlq3Kshc`kWg{T~`rGXJ()>R;2%FAzb3>Gq9tdAEkJ{dmmFQ2n! zk4Up7GuMdgoJGzfzS9n$=yd~zt z>vH7Ftb;ljk?BCa0q- zpIL}D&*vr};GHbKm727gj;B6vEU@oVV#r=pK*$!@OUmv~;auM}!`icXhlNFHd^%gb zr{CTs(feAf+BJlcDcAE_p#tQhLv%3;jAJ?1m^oQxKn9&9p9~Pn)@d@<8;;78PgF66 zl%M{<*T(zvtnlMd>WVVjuvuN@SI6O4|LzaQsoTC?_>ZrInvpWjQ5dID8%3HB-MSUP<)lmMqUf>W;Hd_vcD( z3;IPm-1PAAC+wN_sCGghaACaJ2xCy4gfm+%*_(cg?1&z9f8 zFFVEwc}J^R7jA0x8kd8(l~%3fF%*|Q)>QKV7(J3yYgvg|f05=e>8hzZQ)f~+p>f*~ z6OTa2U_^qUvczs5UZmW@Ut@kJ6nlU16*8|370V*EoY`t75`p?Gonpc_w1>zau+{z> z%LB9|7w*AV{#RlNk}2y?#@hRdPekA5Loj@@@_)SOzkUxyA>F9W?yqWT(CZ!=D0nZ{ z&*`umU1dJTtLd_jz-v#`XujB_;KzBEH$Ue2A*5noyY8obyGazk8Oaq%!~|?dD?B)>)H{e{HTD{0I&O*2cZe0cC!JB+ANxq)|5{+Z zp{0I|Kzu-Od}p(GwlONjMHs&usb_Dhu2xFfGN5Fkb_pM}#HVk=;yTcajASz%Xm1W}Z@Ik)#5&&dd|rxQ>$lV!CZa-_YoqXH zt0Jk@YI+%n(yaI5=VMK@AKmoFHV2Whu?azk2m2@sbJcEP6QM|m2vLzFV%z(xonQAh z!rNZxZIIqcu~YN7>e55-^Vdgv3jp00zq zUeHp>@TUm!K(q+pYhrxr5)#@Iy!Kz03#I$yUg&KOcp7Vn_n&ARRz!RkrMOZk0$%Nr zkxHf7i}xMR`S{J#w$i9(+?KoVl*-EObi0TQC36)LZRnmbkvJj8GrE-wB;FURr2s|d zy}B(pjSf7od)CdSt_U4kueYOyKh~%FKndSoSlB)5%zB@=JuBRsKTy=&~80`U`wxQ%CqQr{!X$3|rOqd`Mq!Y+8a)|Gamry$`+9dfN zB`lJYzK`TlME0^oz`;WHWL3S_80yno z_1a?O2URgcao^q3*e5{?IGk^<1HO@M%7TV917pMvQyCai4Mb1s@0gsgq5OmwcL$5!yq6?jDQ^; zAB?gsWMsTf6M1VUT=0|w6;bR{F&GtV^?Sm-WosoZ@Qf9PtbRP)L)ou0JGt7bxJ(R+ ztPaH=SDRrYts!yZ+RhcH*dkljFovP9cpfw{I?D0U*^JJe46QR)-;0=DpPX|rb)Ud zsP0V_+Ou<3)ryqq#(eer#o}m0%*~TeU~%-DeR-!d+Wo_XAMUQR6#X|xJz=sATd*RU!PY3#CFE-~$ zK6pM)vtY;ig=j+|TN2o{31HzbpM%^)w?g+h*!&WnTsD3w@^qt9+G`8=`!{To zGZop@l7^2zu`n?5n<6?*`SUrg+O^qeXf!#)po~*GKAg+@f9PhV*^jXM=E<^4@sr4^ zp}hR!b&W^6V0U}H#Gkd337@=N&2zK|k-pqOL8)n$uVoTZTg|X$9Gervtjj|D2b2X;LK$5r{zSml2}6t%h5rJa7dL( z!{Q>%)7r%@2L7~`7wf~^v7$Sp*|wr_6;&w*^S}+-yhT(>$UMXp+tY6zwKu5McK&Cs zzgH{RVS;>h%tK}o>`S(~Lf;M`yKYo7%VINr^VD)VzP9PpW+&@x8Aq00G(&mc*LVnu zC&c1_ZspvOFqz8%u+s+?5coKP&E2j7M~P_}<2tY#R|eLtAGPsOfuZOSv`nx^;@2x( zYiUtmzzeF}xv-tsWu)JnIbPi*x~5KHgGLRm3ho#y_?hfeb#h;AoA2xYrT1XLElZ`J z|3!%o;v%VDH%BJoAo%opnESEsz8zPx?On_zctj#3Vk^sfOorq*F2RF77nVn2?C zWz@T_FoiX<&jVMxSj|{l>r-i-A5=J1hwcn(I3DzMTXQ`hOe&=L(78`r9@}7%^l0nc z>uqfxL44~iZcuYkB+dK2I%gn6F5PPJ&+O^1 zdv*hPx##-+sO%tO0?99jtXKEU6>EdX$RG|IWZ{Q0dRePGHQ5XqI~Zu26Tcy$*&)Lx z1ntED;dY5*9SfG3-EEy3!Ji}29RTh)4SxsY&S_WEbo=1%I$EapNT-9gnA6S4E-LlG zV{NdPexn)Dp2>LwlcTJ4jlfjaC`-OrMk<$&bfLpZhs_o(z2)PpjKa&)~jY7}48b;y8dKN5yG{ z>_t5q;EyXldEG7)+B0oKyS*K3ZGAn|cxZ-|tPf1bgQ>GSB&0y@A$z_(`Lmqh`AgVQ z7z07?6K7-~ExN=K0#Pn$_XvX#90YV3h0R zXA-LjpII>0mq!yQu zgx|>RDRtp-7ut~=g3RrZk6NI{x7&JDgPLy_b5+In(K+6m16iNYTAIypFkd~lJ64>+&W1Z=@h7tG zL4D$_Uz&xIeathqfuTu7&!@lXfT?$v#gHm64yK3}3pM7(5`k#>^gRgxphy$Ygg<68 zOMp95f4Z!#tvT518R0stpi;829pA<;s36a}?8s*1a-rzFHF1k!9!#N#JSInjsT0i> zwY@)|G6Bt20eQs{1EiO*f)W9-YWcFAs58sP{XH%Q(YiN=VaaBMsxKk0#JnMfGP5(d z^Wc!;+8|TgkzUTIEXkx*_S6~;C6A0GraQf(P?p}EC?vAB-^i~+$?jK40I+Y5Ur5sW zc)px$wyi_f>g59iFeo|2+9r!mGjpa!yXY`O$;@`G z&rr}!S26u1gk~xXHh{JqQMtwx&bwfI z&dboME}R>GJ1_U}@bG2SOQmE6DWbl;AIW!>Ldb})u;MmpRdzpCR)DljqoM?5BI_vr z1)X85X0k?YSs-iiK{>)MDO-au74I3Re*a|g=uv~&Sn%sm;WPH}`u1k7Vz;WsOUSX% zvt%W^B2Zu+B8ya+LxE;-VoTWEWvYxp%E1OF7r60o9NS~7V}jqgoK3lXZ`dBeLajy%)&M}fJLD<04BEY5PmzjePSZ{ zzS;3z<~$)oTnJ6No>!qj16C~50bW7-_ASo-DdZsq~yg(&GACR(Evf z)a;e?oA%2^Br;=X=e8F=j{Nb)Homi5)XZ5Tp=|MAL@)7v9KU$zFa5fat)%I+ zJEQV$c@=N=9vq*W?KqeyE5`XvK2KVcG9C%ZKieqH86lEQMU??BC4ET%>n#UGB)Q*TQ0Ed9I3k z;)?xe z!noa)EL)2!xn9#c2!`P1@{N7Re|Wg{yHPf#JAY<-6K$S!mjU#Vl9#{J?V#R`T%hV9XsvjekVvEBE)oODKdm5_EVEexPMmS|jK8qro zt1&4)r*psST<3@W!LT?EVnxPX+wYQ5(E>ftP9naJHW$mv4Dx@X@m-gyGtr(GLtU$pm%j|NI z?Qys-ecW@8x$l(rJ;;duWt;US9GdrJLfg&(r`tv#X__QbH5wc1duDDn-8%cj86^zC zgNl~HjCnJx_aMF+pdNGk5NZ`0LiVa3sw)}W=?^_3pcdOj&`b&Z_bF|lY|Gq!uKV26Qtk0Yux zGpEx-vR=iaq*RvS?RCoa#K#06h&|t**X&iZYIzTGy{w8n0-Y&saKIgk2E*4g*KbW& zs6C7=O_t*=O=&qFE98PqXV(Q?PD7NUKv=c4a7)d#1wB7#TkaASmH_82$3Mule?)Am zGS%p+asgGS_)vmlonTvLKKJl;PmQ{(HM5)sj1o++7PKLDcD2;tkc8{mRnn%3`~Ha4~ z@rPLN0c8&~(cxu|xZ@2cN3j|9VKoN^gNer4PT&vDjRnMYpz(k7Uioy&cEfjtFIQ#; zkUNqzk2?=oJ#mEo-qy2ucJP|z2rYNc2T?&rXC;?goCSxFGM$7wMO}GU^jKh${h~-^ zF)=#h8ZM&0Z+PQ`1DA}(;T!ZXQb`Xn9IUp{i#3lv)I;kcC|N*2rdZK9wNH4?{<1qD z+~1G$+rD+#YyZIW(iYsp8`XBkEpctsyRMF22q>@6RWR;;FK1hHTzI z5ym<}C`1r`C!Mq6cel%yd#F9#oF+~gp`wni2qK}4**z4`OC9#Jn?iCNuSEv!fEuDt z4}7;y?-^z-=TR2r^?DQH0}@i_8s{7IA((W(U@ z1^YG5dld569LXQ?z;5JdG%~qP*1CM~Hac+ghp!5nt29chPEAE4v)eAbNAzp!LdQbv zk>kE6n@DI6J$F5I_n_Ms+xyaYe~BRD*UCqgog|}CS@zNMh@Z&X1(AL$N?T4j=WZdbwKZx_hwo$P+NN1{q^rF5&P3sv`qBOAK!SA z&(&9|-{1JleiLQH)HAvj(R~5nKzdQ_WzObN4SvB;38!q1@Fz~u7XP_;4GzmPu8FOj zUOzh4g0X%3xvfy#oPF3b+KU^MEUhKt(kbq{t0+l^$K~uUcYCwRqClQY#z+~QAJKZT z664*yX`Z6=4_)1E{Nbkda&Y&$SPigTvfm3~0M7My-m)TyN6>yG7&}SfUXODK<|^N5 z?V3_C;%87Fd8lolo6RLteVu3N>3}$3NUcSm`58O%DV`R?yt4VQ>Yzj@AFZv&zqN~w zt~UGfb>V1aKOLQ9rF~uYS6fHM+0lgkgynSmbp}1Kh%4wgGTT;eOmWgl$?etlQamIA zsjz3Uss)I>YKv}9W>>A8!Fx)sQ5(6EQqO#ykAL}jA3-Fg_rX$;fLdukUV2bs){-O#?O`AfNVH9FSA~5PtXK*fSCXUl> zX>A-G%LNzYp4D{eF?#8Qjy2a^2J}bZmJU%uzViKG&IE#ZfxdyEQhq|aGt-!M!DKNC z?)S%a`Q*3AOf`5jKxZv&Xaw2r*}lNf^>7_0z;?S|OUhRKqw9oQF`n=Y88?HjB;;F) zqqmaIsU~#PIvvJyTphXxaM$!j@BLiu;ZF|mhJIJWn!};8(15|#)D=T!SAm^P*w`&> zJQs_*Z!%|``zJ5H}=KPCoHGV z<{m!lf8U{k>xRjJbGaR3-_p1^BcSO?-3xtT!+70k8EnyNX+y0;h`=Gw9yMN~=GM{n zlAF5fb@!ncQq!$(t*6mwlY$#?5_S}nY(Hp6~9@|mlEtWJMH*fhe2}SKYPlM+naCC{;W@T`;}Wod|ryK z-}qxBe{FEGBm|2|WiP)NAh&+XCNCcs+V9AcS6qT4wg=(a=NX9s6|GW`tlIz5QDYIv zT{6uI5FnINh9%Jo>9oN--lsX=UpTdT^A!=cCO;&|`6<3aR2;SAS_zzih9|^+DR}4u zg-{kb*d7{VZIJC!nG-6a(hvgk9Ei$C9W-0OH|ZZ5=S=)RtIPe^_O}o}oDL#DTc7y-`(vMTi&{r|5qdXEU3-$KGGUj`^tNI9 zd_f|1HTFvW)*Nr~)VXfKaFjC-bcliMP6y+7!A0=uf0mYeQ{e+B2oC?&80}@dJaO-? zgZrnchBTOItNQ|e9 zpfWf0U8e!-&-$f=yBzbGt1#@4>B2c{y){8a4}LF4p*Puk6LDJMR$Bwn5_?m-9+`(n z;pQFuwoG%{R~12{@ZL7lwUw=t``ot1VRrxnb)i}4#CB~&$mn_9`M7?l;Mud{)9BEA z6bo;p`3609UnwFn1qObzE7V1h$x0Z^+_et3)~%|t66L$kGflb$ZaH zqr!UShwBvSW0ENb6Vc?GfioN4+nlDSqyD10&{+^ar08zB;*&XQe1SI zy9rG(nqc%+*_?guFR1r`-pVuv708G%f)qB#veCEH4}+@ReWFk=z)NxW5$2Ceru5zs zsSAxe3jDGRUDMlp-pz9_ad!|8<_M0??yrsT#DHLPP{)#*RwF1HXu{0BYP8>pRO@z2 zgqgxm4%wfnR|(?`=G7C2(HoUWisaaCa0|&qNDanNvJkuvm8qkXv`MAgOky<4K>R{L zmSNq9d+7mt<-+J|U=C^huR zjIv$=py2!F19TZ&J=p!FR->d%vpybvmqxlGky_dnV~DOf!=@iHFAvp5As+!=3U%V$pF@01(*XRy}* zfP}55<*K?w%y^+ajmXPwefWy`4tJ%t=Yc(!q5hgS^HNr6qUo|tXtHEe0;QCISo@@N zEHicD_QUIyK^#5pxy?sNB(wpL&ROMJhj_9V9oze#&U>ugrplO+)>laXD=>I zPT4~?oa|a79`2F%JDO|`MKiDGB_LGexJo^ofC`Fl022BYh0;I-N~t7_lRD@5jY1Kr zaX|mLnszRBRM==~zAe&VEKsVP+^75k_ii+Z++!Yx&t#dvv0OGo@u6B&TR-UL$B%+K zd1odoNm=3oKmVD+-Xm9e`RLb~)i!H}#YeGZGU^yI3gx(>^y=Px&!xL=5V1{T5Cuvt zQ)XY+kG3YHp4N{s$yJDM^hr|IQjWS^9w@C?CL8uwbV!(r-_>cS<8o^U9sBqnGUTFY zaplSi3do5|kPXDrm z(-wSX<4wS1Pv3}ZEXp^IDL$G4P=5P3(3)Dol5Cfa*KAmtvyR}Oi`cr<&DnfBk9DUd zi=PoO-uOxgKpU91Ubc1562Wr`x1GXrWh}oS`x{OH3Q3Cy_tnn7t0|?=BCL0ek{~-= z`6e%vDT*$P%L0ucm&JY+jKs_BkmA0YWBe%T@BEw*Uwd{C=QdEOR^=@ZAC%WL1(gID z7bXx$aUSP!JWN9uZh!m6voqG1+mr<#5OR#hkw}P1qkj|E7k?GxKak4VU_zu~_rcyo z4?pDN*e1kFxI`-1Tt|!k<$h6dgAE|4sJLihHmInw80(vDS-J5$si)tyTp}2GbMob# zmP}Wjh-61mu&F_3MQ3k|My3Uj7&UNV=X5>_=WOhEFp|sdZ802Ja}b?ijsdFm@BxW5io8Zc4BZ6=ImSt@AjeB zjiqb7nGdQL2rR3Zt*U_O3^TS%%|7P<(Qo9Gp_nP?u*Z=|uTyrrDi$bsyM4JWBel~r zI~{iV7*KF}O4~9%^LV|bh4JxQ8tb^~YD)iHpLA6Z+6yZ)|F3BL)WFYPU&Sbq8ZW*- zp=%MsYW(tr`>}u&6%q<+uRV_Xkw}H^!>EAg_m?Mgqf5p2DQqN|j&qzhKq9OwNYSDt z7pvWQkB3?Dz-^fzxBkt-O;Twt>q6WjKYGxR!mDY=Hgx`u4Gb+3OlTo~e&t5a`mSS* z|D)?FpsL!swIWD2NOyM%(jeW^(jeU^-5?6m-KC@ohdOkJba!{dq2bW*HuwJjz25uY z8-u~vhcVb^uf1l^Z+?p;b~3pP$*p{q8L7I*Jlk=q`P$Pb67%y-EBpa&y_#U0+w8b< zoW8Clc4uYEaLl6R=E0&s=nIByy6@zaFvS2Q2mgTZN^PcM*)z~+6sEHT{N*GlFNEH2 zvtOHl%e6rm4HG#2(>UG0?KW5jk-byu6AVIjbo0%iZXyTIC?qqmpy4hN*9zl;v4QC` zCL68lbfeDNE2MYo;5}?4b-be`U!Gr0<@mTa5Z+!* z+fO2ycG)*EzM z@s*)3GZw|XxdJzhTvxT!0cRLrgncD;#vd#f_{k0ZCo8`>{Sh)ET&jEF6bMcd z9$%c!bFqX6hfkRZ9<7*(S$}~1LbP$S_Bf`p#L?<+32OTU?_YmNV0m|>3zt`3?zSXs z9`lDvu%W#o}Mbp zjelFSb}f~W*?Fz%HO{13wE)6OZWjG7SV?pei#}SU8KvIgtKdbfQwdBYNX&p({LdiA zG3tr1Yu$D9#?McSLiIL*wvdOFV7QZQD)gQdE{k#GJ<03n`kS-Z;o)J^U@x`cWS%>w zKKz?ThPVn29>(^*ckaqw%T3=H$JfX~$l?w=!%Z37cB$KZblN#JV!t&AMS*?`t?0m0 z$>%SasUL?2;Np)LYR~7^$9F~6&lEwqdOPLWZ3LVCq@^L$(RZ-rjIT?0y$GE<-b|GB zPl9xMi)KQCeqHid{URN4-;Nfebi@olb3%qU|z#zTF_c=x` zo9-fVvC$I&rJQ2vp@uv~4BBudqEmTRv+A?3@a3eFe9qUtsBIjHSmaD?@K&?rN|&x3 zpXiW?WDYH=9Rpu;E<(*E`x@Q?^RVgS+a?^q&{kP0uQLS_W;26GQy1qD&ljp;cU4h3 zcpi)tA0S4$c&RP{Z2@lV_>sHf;zW)rlax$*vZJ;}=T>DAnCSyk(q{awe17}M%W!bBW)1771a8y%fzaD7Z9ooi_$+>Z7ypxZ3hx7aBN4iHJ6Xe$ z#w1Ffm!~k(Php~V5Bj@7!Q8Bh_iP2`rxr>5DK{Br;izV703E%YNuG1tGTBs*Zroy- z`EzqEBB3AEdNb4m&nfbcvfC5l&)7{93qOp;kpe(%_$?onIXYpsBxSufY{!yFpOWG{ z*XU%A_tIoUWj+KZosGAeJeD0=v=GM&)#U9h-6M*CzSmDh3DWid0Kuv0FiM=+sC@5b zJITGE2a4w55$t^kpS4Sk#Q1U>ZXSU)W|y{+U06Xwn``94?Cs=UD?=fj)6+}x1h#V> zbNrv~B(DZ~r)O1)8==+&=Vx&zKnAj>FYkM^aQ$jKIce^1G*C3b~Sf0V_Ng%~4TA3mW~*?3m>mY1Ej+kwsd8A0_f7E-yJy$Nv# zd#(lM2Nj6n5#DFV56(DNV7o+GWl_;l0b(#)qr7rVwp*SnK~j{ zsi7a2JW)i+jECrRy0I9s?vf-fFJ6(@)c2ZClS=dIb$l?kw^^F}irVb@7SR@)2jmMZ{2~ug+4n zQQ*z#aTnzG6wm(?B?9hK1(+RAlnKqH+tBr?ruEG1}PT43CTPcNAknoPR~)GI}j z{N#uNBrje7MTd^@^Eli60f42#r~x2;{M;eH@fz&d(}phv=QVf=cD4pHrofS9*kqLp zF{P!{G(Lr4Db)qaSyebW*XO%C?@Zpk(|A=>Qp9Mkkj1#sOG|K($>%lsL(KK=I;3l@ zg=MbFW5a~U+%^?ntv@~kdR5S4{*>xdGDl_=VR}FU86I=|6s^KI&2qrX0AdMsA=@)a zIstB>Eo}5G+Ib$F0)7|O$UsnNJ!U;HOVjsr!%YiiR%NM>t(m-f!Bf8c=hnbY>xpQl zZE%!*ax|l*fvsNAbP0>0)dz^AOVs5O&df!#8_lL|#Ua?#G3lcD*k4K0cE0!&e~gYb%l#F>l0a9o@xi_wjjs%%#W4Ey8!+>x z=p*B5pT6UiVH7AsPK4;r_1b~Qm1^QAI;p}*Bt$MtvGNJJE2)TYTd#h@TMnCr_jwW_ zSejUiWaB^0>^yxs#_08F+t>+Xb;$Hya)T*f;xWdXUV7NMXK!suSk?oeVnY-5Suz)Anb9#)X%{v0IWjSn1PqKbWzf^C zMX#Oj7MZb_=tAH7I!wQ%rB;rbpkBOmU#^;qA&;wFEX|z7Z}DB*c38Tn7QZX<9F#qD zw_9ogF$3Kvf)9s*nug7{*7?imK{F;@k+InZg2BrY6i=lAxO&dUub&$_Ns&>JNo}as zmLx=VkHA~<3rqxwdGSm_^4@Qdi3PQ4S0q%?qV2;z3*u!lDL|xdTmD< zQY!5YL&B6#EQ8MEaG5Mirrej)9`2$z4`x(URq|#wka0U_y3e)Rq$H(i2{=}sw%LbA zG`J2~ZN6pRn-%`vd~*<-`gsj#l8scx)p%bfF)<#*2VBe7l*wC zpJarc)|64z83Tn_wsKayor4e?=Bc^-{Ac`Q>cHCnlQIpf|}0_?h}opOI@ zRv}_MqsD7b=SKZ}rL3I_Yl!$;%Re(=Q8^gD`^s6l3a|I&&FOaYm(Q7^v_nE7I0_jO z-R9q?@pN}a0_S8&_!?H}ZSD9eXW@7>g2cyFMlg((j=E~Tt!728|YR@zeVJQqmqW+c>IC%M9br&Cg^=dS>Mu-!gosOg2*=C8{j4nPTN! ziIAP$26%vSV3cQ~CqcTqW??TBH%QD(QG-n!FRRw8^Y}@E=GnKakWut7^+8%C2b^vP zf>++NNwXLvQ?CI;o9RJONy942pn-)e$YSGVr0`}g{ro{Xw!2oa7|*(w*|TSX5RcR5 zsX2CM`>Co*gD#O9p~0~)Cz=%2a8R_usasGSsox2~#_hK^NYW9|J!qm5NrhcxBg&1Z z(N_n*dgVi*)HV%Nw<-s04_D`*}rOWb#*4i%ADKhmv zfR@PF8ZLhVfF#F454Pr4!k=3!XApDt(K76lvR>S0Td42PSL!Zio-_$wc*h>^Kf6GG zIWqyNCl_kRLG=5c;`fO7Mu3NHZF)ZxIk|T^Rq5q$_w`FO%NrPx`*kjltAr`gUA`VY z)LqoyD1W*w%P(Pi`faWIake+mDcG6jWB3&9QmWJXOngt1#TiT3d&$=VJwVHm-ss`J z+CT(fw=|ek7L3w`V)WQ0&C?F6O67uPsc^;J zEOK@C@_S$2J*J8S$mmm05$w9Y-t^wkf-SCu>|Es%QW!YYlPf&KU4k~FFsEnAt8V8F zbE#K+t1HHnH8LOtw~NX{_q4O7`sQ&v#|+^tD-tbzk5itHdn==P@-Rbt?4J%NbE0q~ zd)JRYo7J9#*p4J-jVDX%qLayTGdBbEm&xfM%%0(!pdDd<9|eW*mbs-zAjclg7G)m* zF{K39PtHw(Dh}?oDJ~1$dWU`Quu6MPz{yTG8eWjGtM64NTOu{WUXutiN4TFM zsx@BM%=GAN{Wfx9O7nELOj~x2cNd94MNY2zfWE`tvWUppdLj#}%qUVX^wl;IswtC9 zOE4n&YX?_^GuiDnZ3@>rd`u@UwIdsr!TRvOtY> ztPPeIJaEyQ1F73IO(lc?>h3eM!AaWUFFqF<_EIwFvQPPkD=d%w1c@Bob;{zQ46 z0+$qRt;dixctI?q&?~e=V#PJs>xU}M26T>puZYWH;Dv%-3V`8jjM&5D;go`?ln8~; zJ4EuzyTfHdujtIx=I(EA`zURQn7&vV+1eWQtwKCsT6JRZYCjdOh*|V{?OFe%i%@F$ zZM$wP!NsW8HMEM@uSK4R*km@(+C6#klOiTc%>bWU6?f3p`Q8*bw7c6WvT(aqbEPUF zJW{Ko@v-ZDUmv$Igewn+$wAR6+^>nNCEHR6%Sysejwv$u;@@+WcF_^V5rjfYI#oO5 z=f&3ayiDSnH^KX?)k~@Gs?w>@1Wi%!olEqVYEroE7Nr1M+m}pzK-3s*OG_pw<<Q=@6hfnx5T z1*(1^l^XAN*l+PCK@-hi40`m+!6y27EIJjxX5lu_%e^iPm~x+2y+>>9omm>p2zh?ky%p*H zL0F9m-PneZYwt+k992Nvnhjw@^I^z=P(~p}iIGv4k^0g^=UdTkaKP`4(3nAJ&%Tu+Si(PY&o- zPEAR6Fuu%nnTxdk(2{d<4^I|W06qjE3F^tdSzH;~pQhX+C8DNFWR9uneuYSnL2ukU zoqL~*h^6zB*}~tWJAMXmv+zFW;zRh|>y&W)Psz%%Gl=-Jzj$|>ViqB)n1)@u!!dSTQJr?{~>>|uxl zkOW$dwryfhyM&*Wl?E_E=%nf4f&!a6IGHK^!oSg|k~1N^8q?0mGn3SPD?N!pue!y^ z;I^k9+iWcvB7_GL^d5+#3iFNbvxpV^X|5>$78!A!8Rp9{(LObjjWqzojKGVFHCEsM z0s9f*d=72v%E0M^}SUqP)G?LTuF5Vfa^XKH$81TSpu>`eu$OCY3E+p~2DSHdLbFu90mz0FntJtNkQSq}I+Sqv0JgsOcmYYKM`sY?5*ODZQ z4YY3zJP#3H@d&8`vk!e76tu2ivm#fOV4*daHKxI4osBpbv|iL+?mfa@2k9CP3w4zs zmsj1+(z}zg{GDT4#1BvU6cnW?zC=YStK=2lBv*IZOdPTAd@zfJW#k<~c{|kIh}@+n z)1vgGj?;OQN@Qs2zoW~4%>O0%iwLjQVf8EBUADVzbCKM?SE5_jikQul%6cv-VrQQE4BX>b|uoVdiJo z7nO87E)@v7Zwun0-E4zg=AdiNo;o$sV-Z|7XXmH zuLQYyii@4(BF~Lz4e`!@IXzW-;73C6j3ZRLkCv^I$UJHh7_U=8LPO)IZ>Zwl8hwA8 zg7ndLjk={O@~(vb@I1d{npLL=;e`$czs<(U()y&j;FfWl&p=I=5U2Vy#)h!W_X7s}iy2|fLGm8(9+ zqY6zd#?s67mpBli4c=6UTkFG)b{jlHS*1nV8{Ux4Xp3<=#XNsbSh#5x{o)1ZU0+G8 zhT0ERNgFR<*774l)5G^e>7&JzM8Wf4Ihu(#r0z0JclJ%tS7E+wJ-E{Z1VYxi+5^L* z6CSb-@x`PG1!T;_hN=jF_k|}E7m_Yq`d;-(M zs0n(ft7B%6<=mJ1&&SKfMuHR{xhZAma-8Obc)SR&@C_;`Ea_mMPg^#}0A=sp3H|zu zZL`XsE2@Q>ieO!~5qJqBacW1CuV^J*S@&!`?==^gNS*Z~GECt-OO1J_(|LS?c(Nlx zLSh!YpuK6>bn*{k;zINTjYT`PonwStKPJ*MRBF_0w4|V|2CeK@Cxt0>^sg9-4wfTG zq4YZ;^oKv~@DCl7+&g9$z!yT-v)qVLB0OzHa*xwA0I0GE5jWZKBgg&X4cShanVGXw z$He*Gz75PkPq$F(z(H;|&zl)Rg4!G#^sAMwtcs_1kt70e7kOwI=?_6`#A!?Yz_{`c zf;D^@^96a1p4MsA)*tIOC5=|8#o0{rb~B!hMYP!sJjU5gB^15S58^I;q$=cIDYPCk z!(LEud320zrK{4&>$v3Hx-C7tQ3CpBj}UhNRCc(Vmqk&eP=%}9#nefd9x@2jWqnCG zM#QTM5p4_y(#;aWZyGS2GTzP29A@-%(IDnZKH=wd-Vk>xu=$%R;ZJ)bO8y!;&+A-D z{Dx}}`aRfLP~CWvB>ueItPdePY%KQ4!xKBp`HO?a>tF)#SzCKsQ80opl837c$w+zSyATM@d0kT)vN;A>sBi<(!l_*I$smBBzmy zAC@ZV{5m&wLQ24)_ceJ-tJi2GThb*1RUIEgx$kLnMWpP|l`~RnA_CiB^ZjjLy0DK< zRbgJ@D-Fu?Y!!On4PG9P6dQ?-7FPfV&;60V4p4Kp=}&E7S9&;G zyVwBok87P-VA2c<>%aH?vGp!=mtxXb8Qx6HBJKAeS=DfqDk_lw8QB&~k(?q-Yo4iX@69XvW;l}$EMh=f| zFtM!#mDBzGrdp<+&;IR(ffTcMNsfIKz*riIx3(n8xwy{!+4SDtd&_WLr!qe4n}^&?2U z43sD5D(o574BfTKJ~}-$Iqy$A(_1?Lz%~0pDva5VOABlx#)QQ#PK|R>$F4Z`UNegZ z!3(G;bA~=bJs6V*Dhmc=l)df#IM}*Ibb;L-gTFYk8^D4x?TvT_9Rs<~_0k;u5gght z+kF*MThH%?zjS51ct(fmYVx)qg&0d;zj?8V_Kls?0V3LftJmo_9$~-H#EWJ!F#Hg)51X3BOsKa@Z-dwGs3lY_0TnJ2n3>2%LpMd+8)CNK#@k zl#Z*Q1P)ufBeW|M2<+)@>@z^0I^_wd`7Xm(W}Pyb@Qn)|2O(b7x}4;ZxaE&2az#qrElJo3W1)PJVydh+lmW> z4uiXck=)@C>ksy;x&VT?J8(fy=Lov|I)zy{h>`wHWrN;n zC!K2X0*Jd4%Hx;_oXrruhFD=e@~Ly0@1D8*8PIP^k$loQbr~I+)G>UaM_`h6{Vi}M zkUX-LTF)fh4(er-LckAuhQGZtOow@#Z`^KU6}}I`?)>lT{pOc8B#lCv zg!+plEXA}i!>?KC8l-j?zW15wZ?GwkS5h9?QzXcRFg;f!aXVjQyjm|KGJ*ejm@K8| z;|7@k*U#@`nBjLV&#{DGBr;$3;KbNkW!KWmE10!&_!UI*_5o=8SV@3D#FR5| z*9Y=!!WPP-cTGE;ojs#^c8{}%CmrL;>ArE#n`IpohX-5rNDh_iGRg{1V`J#`?`{@Y zN*Zn(?pduI(8H%JfZhuFeAf03{?b^)vaYKX)k_g>$kW<~CW?F+n-Dj2z>4SiZoQ*1 z&;|;%HQx8lQE>zyW4u8YVkxns0lyeddW8W??4WJeXO>;>bCJt|QHPuuQ{M1Fnep<% z5^Ez5Myc9Tu~K=v4b(ZkK$$~tdFdPb#z=1bXG8%3IhgDz4-3q9EHA8zJJFzUKi#x4 zkrrJP-C2Oi%;UGO8s@4tnoalJ`qvJsd~Vn9l}p~cJtiGiQ>>>sj&mg}6&>2tjpMW1 z)>%{naYMpE9G&SAEbAS-4`&kb%KM&eck3ZtWE_ey03SwAW~0|RkD%pR(>t;YO{q#4 z6AgD3-dG(WTJ*%?;-&Fo#G7L)&>Ww|dS zy38(nlbz;By5Gcl>v?EV3CbQO3$_dh@o_9eKh%B_>S1CNa@hAX?|)@OaySP}x;9N1 z*mNb}hDQMW0&IRgxDLKr^lk1uTroXwFiHwvtcRGr2L?TdJE!G%gCbG%3I1e(8qWJ8ddTw6LgIRQ zBNMf8veEZgXb>(o3)?&ym>Lsg4TQf$3utf_?h+I*5WYX-LM8jwbnK|qLkv@fH`F(% zOxx4+gG>%GV|lE0hzRhFQK1^R>mp4Q(cSO3_eArtnEm*(A?peQesN#KTki%jQr_f$ zbc;2L{uh|lDjZb55pMw`bVpZX$QVM*Fe;eJMLMkYA{opD_j)wGyO-~JRg^CMS5!|r zUpW6-p-?uzAc0A75qS^P!8L}C7wjJb0%6+q@V)b-F*sbd2K8r`!R8UWz+~TybJB*@ zU0GRK-Ccolh9-8NO=!+YPGiI6r8}P|B-x%QJWUAKdso=|@=N4!m`QsAxG0p7u%aNc zYyJms#Z~@V8g!)iiqe2DlbGsjW?qMMz8klwHz4o}Z%t{$+KuoxM>zX6(mGT2b z1>-X@KMC^9DY;BgE#AIm3C2e+E)`3VlQ;oV54$Ho=AHsl= z^S-}oUjTOA2sXk3_m#V|mLNgN7usg&iNNnvZ%f`ZHGI-Sl|Q}U$+=*4yNT5v$~u@F z@?NBR5}c6yy}@D^hwpC6dcU;%QZXWLcNtT){JqmLx>D-+a-)tm7UGxNsuMPb0@`ml zS{M7n(b3Ki_HlV`2)ROvy#nW@I9T19Fu(w~7Fh76ZzH*n-#f_)g*1pEMO3sAHdNT< zHE_DM657y%<|=C^{hH0oy+RMQ9~Tg!*yeZ1oP(N^Gymj${GFoa@j8H5`UzRA{QR&w z);p7N!=iM9JGWK%t(qPzJQ4;Vq>B04W<`XvSrZ9vrH)ntSVv0ggQ={svRlk0Fgo!3 zW+>Q^K!l{v_bg@QjlKjS^zY!}7bUS7Dm~;?qqs%M?>DqKF$&_Xu?c;oH?oq10Vjp| zTAUHnWzc!`Se4X|O_Fbba7{#`0xQB4Uc#fC>7{I^d^h{?B05BXNvoLpQeIw_NWh9@ z&sqcpKaGLydWJ&Qgsva7yFkG81J@L2ZYI)IA3U?UB{emQRL(5<{7_Mdxr?gdl7)0w$Thm`pXU^KNKfJs85E2!N{qW|TbAOUm z^(JJCCfC&JSgrS8w32^$(*InLZ($)I3={zTlJTD|Vb2FI^v&WMrIbppbyq3bCaQet+IDTGyGfM#-2w^!UVLpK1goAtG= zH+`v0k|&ag!s20${5T1l`m5+y^&P(wb+YR(Ctp<6)%9S>Z28juuM;Q!Mz$<71ORzQ z0xv|9@%6iC2zV-`e9n%7?dBtay*eF6nJijTE>hT2pQSmRM$pERCfmJX-bX0+1imY z{U2}nH~Oa|;iuk4tR5!F$LNR&Ew^wRm!lmYjOT=BME0MB2*04ftv^d_b0MV9**7}W z8pL|+)B3~CQ~Eo!{#RMM(O_;-d(n1_xWI_Ny7UsAba}d4Jq&wBvbN;ae_0_i6I15t zR3`K`2Fo1V5QX?T%9!&8ZUCrTcQ^JxgUgnrC|eixU6ACeMHTp?iX8y{lc(Qbs5) zlY6D@3n`cx#pRO}wGST#koeB_QTS>hZ)|56PAAlKBtC zGwAk!xqvR8^^svc#&5uYgVgQ0Y>UWD%AB?x2@>RK)NstPY;|VO$n9aE+!f5;q z$!cyce3$$u`BgL`?CbFheyQd`*iz;{4`FU$2%!9ojC@Z|9i4_i{j005!>4||dzEbC zC1Qv(LpAyt6O#o@;AeV8|g9ayhUt zdV4lDdNNPAQ(Q03&jU)5E%AtpC-I8?C5K=c4kd#xMt=&6A^POMzwl9E5C^1R3SGpH z-yUm~-;nvm9?Y7D;7H^`#<9(MiIx~9EE@Gr&O1!`fq(NC&?K<;=1lM?RC3rU>d zHKeJ$xRX-dmqqLnSM`|GE?*B#%QNbAMwFz4Z#Jy@`-}c{g?|hK4c?Y5@yx+d$fOnU z^@_T0z4pC;-^*ye|6F0`E=JpM62ZBWuH`;ae#PqXYsrE2uV?<_R`?MxDeAo%9mO|W zS$WX=C7HgHjo1S@`NdDFKYV8jO?&s2^4W;9=ttVJN8GRUuwf90KRyY7h>MzF!*-VY zzib_;bt){X*;KW1zcf4$qe>^6+~i%PMi%x-Sl5UwsO>4ceb!b<<^Kc*f&72}Vl?uL zE*9KC=^+zQ2{j)`m=(E|OLI1$QdAbCBhlrR-$U**TZJo$JHa+!^uX0fruf$_*ll6! zi1zY!Qo3@XY|U}k!T0%W1cxz>%+zak|sDk)d@Q9bGC`atD55_^P}VduAf{@3d- z6;Z$&%48dR>8LO06=1Vid;hJuUc_{2{>BE?tR(t)t5K)ZrV=s=CtuOC^?LZ zg&sBXrW3%l%aLcu$gGV;_4XFBCPE|TXyUL!5;po8ULB8yC6uAHTap2UJHb)^;b+(f4hyk{&a*!LetG<3VAr z`=lVEWQbm52pJM9R)9FhvSIL_Vw5UcS1)h<0EO4~xx>pXtdgasiWT{x_d@?lgTN08 zr_MrPBZ8sF_J2wcpheLzQ24!Ak1m<}OIg)A#~i+2EI92(LpKS)PDUSCxxwq4C)I7zu%L3+#uo(DpFtFua>vmf}F{{S^Wk=b@mPjn>(q-rw zw~GutwJNt;DswH=l|kg*6tU~{c@x*9#6MN=?}xx21C|2Wk21C0Sgl6@6U-8AyFj(q8aCX1Q8a{TSj zV_2~Cq#fydi?k8Z=On*vxwNkT5LjA!{^Rs{eXhsV*yz!8;OJ4eNUqNvt?Y#`MZqjxZ5^12R%K6En^&6(BQ7-ayGsOT1 z^zI>_Ir*hit|8i1)L$=vJsj?mSRmYC@QKpEeW^Y`;1!lX6kEQgG`jiifff)+joHcK zq)82;JfC)REALyeAApP}R`ymarx1$EGQ_`L zLQ5;+kq30S0nKaQ_Qg++E3VO_OYza8?Pu3BPJy}gV_1X8@;jp*sxDACRiDi(PWzGf zSWFB;5b^S7fS7v0e9L+`_BFU5^}5Jlk}`ULxqgCW|2<(^Xep-DcZWpIlo}gZb~j#) z=D5yHHa|CbgyKuMGibwho5GiT$M>_zN)JnI!W!X|e@*Hd+yyzkH>1-+BJh=%`BaAJZrN zH7Te*GM_TbAJ+t1#0HbJ7uI$_v)n2~1C4CK#J%jIit5Qdo={ccQ93z2`SkNfI{xCT zo787WAg#$WSgA5mewvm2G@5&`08Il(lbR-Wq`F0Qt5FV%&9BiEDOCEn!^!FoJ6Vhr zty!5NVnb_e>r0Fwx?Botu8_%0u@I=?Rw_5+{F{A633`%c0x#}jd12*unR!{RRr_-W zmo9_iJnBx3u+m!lCVzkQor}d_`dWLe&XOf4!5Sj3-$Z@DGWmv9dcwGpve3A~X@oLX?WixAL>R_V01a z#0h_~W{M~>a(~i4A9czF*a>L-ZY5aW5Rl$tuOR@N`4jFn!M@Zv?uYll2Ozknq(D`^ zm)A77W7wIl5a%T9j7-4mz8%t|Q8Rqt33-9pNs2+u^l!)emmems@-KX+S*@0u>GPWK z41FtNHrF}$?zn-D3fgtrMi7@b|9XavPotMRS)bdaO5y|=?WP9u*9QN`g{&jx*74{0 z^hsGwlDm#IlO@rjnz-4{Fc8@IFcfFeSPVsnstv`;`HWQGUaC?1eSATHg#C-O)-9c@ z;5GE=y_bU z(7#mnuXX$xoGinG)3W?@3R8ucQ3?C)4XZ~At@Hi3hQ3E6R9^kx_aj?FPyjfSK42BoV zoozT&p62nv*#jUeE+VgpU?b~9%X9Rr=1-r^xOXXzj*T-=*y%P|E~03E*taXL?Q#@6 z{GNpk|NpuVQF5)8k24GBE~5>%OQVk-QXdwl7C?g%~&Op2*0zuSaN-|p5qc$I7PwtsE3{KP}n^1i3e^1VVR z9x2rZT^1`YU3z{Nt|8^s1h$0yyC|%utk0fe!pyYq6+A{Mb!6$NFwz?2KOBNVji-g> z`+k1(J&B}u@Az{KHOZLdlNM+@z*~FHknfr3@Z$e`guk7l=(7JGVe(6vKIFcwEo|VfrIx35cPH zwsnYu4(#Q5Y=Fz9b=9nWp|XI~YpZ53xII1YrDPC-x-*Czb3Zy*2K^fKlU}BmUqBj+ zI~e$8fR_)RLj7aM9z|^gbC|8Dz9P1JmxwK??&dH~U0Sv6I9ff+Et9zpBJ~($7(Ndp z&Tv|x|II-BD+VV1C|VAZ)Zr}}F@nZj!(Y;w4uO?rw<7s_s2e|8cwqPDsu!9?325F( zcFFGCcEl=AK*XcXvH!6wBTKjt3XH5oWH z+U}Y)jdk1D4{fMyRX$t?EPHZb}HMDt?Lg}WE9yM<-gHKhR;_ZA#UGRM;s zS}4L25hX;sb5QZNBf7`IH;uXGlC!7q`({LGjBgyD-#;GX@9i@}L44FglbaVa;MJv3 z+li6;yP67+F5M4TMROZGhETbY^chb3oe)kXCi5gxuzIM)K+@Zt8jjpwd6fT9NGfIW zk#gx-9?%2^^mMdbj_I8ZLcLFWr*PIq=+;17c~Ux~*{s}X4GmjN+Yc`4*d&n?)}^oz zR{h2F_C-u@p1R0X#2AJv0LC%RIz0K=DNkQScDs#%FaC!V4$%JB;C)5R#TFVp`qgZ@ zp^+6E$s#}#H_DdDglu+iQ4+&Y;u9tj77D*V4Z;8C1N^;NPXcln0HsK%8X&6pn95_; zs9N~l>Q%kZo#&&`u=;e`rpj&?8*kkKiT&KQOLmAS-_sx&E8?5|DW@#Q<0molKW>bF z3bSMSy3Tb%Zm&**u+4x0#AYdJd&fLg3z8aLu-Y<_qzl^|bfK`Fx*o}1%XQx*9uQ0j z_Yir~SqzBbipwFQDSF9G>kK(NJx=3i;~M~P0cZp-NX5PotTPKu*fdnU@;klFo8-}iF>o`RhEmYG4Aqk+s zlX0!+ORR6EBRXu5^i1Wiv_gwng#(-Rl+WqMk*v6TcMrv2|7QMv+pEWSZBz;exjBin zOKTK4u>ntM+JQ8fO3uftYt2h&sIi!sqE|hTE3B)YgU_RGS<{8QGJo|IT3&mWI$+%V zZsh}1*rH_%atq4D0QGXBfJ|0uqI!J>w3I4jb8s1~-SG3RND_-Hh%kXwZ`UA`C7nkt z`?F-u;umCzWur&+3ZGmqktg>$ir|BR5vPrw9;3E7tWl|2IyI54g38bn#+JuLCgn}d z115fR$Jx1iFyh(2@|3?-i=3SrF!5*HymE7$m4t%^3@n9}43LQ-*_&%rAd`eD$+piN z_r7CsEPo^Sf_cIS`kEoLQS{NyHz1)}sPTEp*pt9Z{`R5*V(69`jd>^KZ#K_$P`x55 ziVaynI;iz_1IVLe(LQ3DY)m?-bdpY6GCLeyR(?f6rFeT=rB_&Ng&2qcm<6cOOiKeE zOqg1nKTs4Jed6Q@`&?GES>a$-pQ+IPG8=N;mqk4h6Yps7_UDjaE%Ws%sw%rxsOHJn zln${`i|XHG@wZh1wv9@HJWiqRa7=fqd0E3^?2YK&?#5`7Rb1|D+yP_JMvuEj$n$3v zAE39As)AF<7P>2O4ZYT(S>e%M16IF_d&>xR>5$F>YP~)Uq$e)bF=V;oFBT0JTP=K0yy8qwN+uyI}A_t1b_0U+^5v zlHMrCRHZ#O)0gM8$HU?sdr~~fXrYB8JJN7Ph%@X6B?hH}S|RU1=@}xvu`i^1h|C!E z(Edtw9s@LX_5f$MYUll*F+8A83r$uTTBy1rx|JomOhOU+lmreUF>POP6tZY(kXb%8 zPWx1qYla}vDkM6l52-&JGiQMneEJxP&;|TA5(%a;a!A_O22ONnKA{9Hmnm_EgiC~( zaNevXb@wBSFqXx>53cm%k@|Z<|GF|_2Et4JJg|8^Pu|^Y3`)x}f7h-=kl2Rph@-2m zUK7q>Dock>$3W^Rw0#CnEnl{x)Sdaw`-tDAfjtN=mc(wf)9i#z9w&+jHwgOWdXi|KWp?;f$`A_Rejby6I zuw!K(54B4>`#cdbT0BuYS55&L1kF{td^2^_9*M2N8BAyBI0Zh|cFBYUm4`q^HLW=MK%eD+8L2?Ck3-8(@u#vt zFmF%Lc9Y}Ve>}o(n-nlY6TN#7J2*=++N6@UG)Y@C$6FjT>B1%xtaQQc3OljXRu;Xk zSQJl*N`#}mVT)>kH;_#ASp90^X;*}+898@qo%l^**;C;lG!w;j8KX@uaTN|T%de;R z3ES+ak~HgWh^RBV-IGc{2pvpFd5%y)hLq|zBFI)xye0)n2ID@4s6B=wsVOx)ut5@l zDTyvUy!Z-Rej(ou11lBu80Ygmtk0Dn>sHHU*UB^5eu-yJX9-JMU^NRfqy(IRsUCtw z$p4q7__rWnl_oOPyG>b*%@fKDJ607URjFb@dVO0b}sg`YrKUfiD+$~@vWIIWMn+V^O$H?<3%tQ(md|76Rw8O?2bq***;p~r ziHSM?OeP|OL}{r)pqfC!{4L9n$EI19zdXx^|7>Hdc-9lJa)DeSIFje5ed?&jY~5Cv zGKTyUc*<)V3D<2uG~;rC0#Xj8DEZBIcJxbf*m8J6I>zWs?0_y1e&Q`pW(AP>;sceU^1*|Jmg zEQyO$+^dX*dhYyih*4m)`Bn?Gqcb)8GmD?vp;{q_{C zZ&1OMadDNIDkcPdY}D{VHP&s`2%Nr7$uj}Q%ur?)bm4SQCysxrg1kYXyBa+C{f$vR zRc`SDI^{UavLh%7VIT6ec|;6X67c(_$f@g8hM=39$xjHS%*fF%$S;TJ?}8( zXUvrADj?LPYbHM~mt(X*8Pe_2{(mb4;bH;K%2Cc!Q)X$`i;$m|Zrc~P`#M&|fO`N! zO_+q}=OpiNfv{OueCCBc0?aH|u4o{dhsGLBY!X?~5W+uQ14e+lTaqv93{A%Ms%00H zrSU0*g{XoMYA(xN1#NouQy~0BSFX`DH>&Ya+-qb*n{ykRnF1M+oOKPwXh%We==O5J z*Zl9?haQfzCzreAwz{b1hY`Lr!oq^$RINn?_@g@yPu*TPm* zvPLVK6}AXahGH)Q0yFf&If}t0=W>o-6;&fd2gq|G5gv5~WRvKInYDGi{8!Td|Zs@X2A!yiH$JR~+lytKyaX zp-1qVaZlQtZwb5RRxbRgQkPHnW!3UTZyI(Hv3l6H7l30aertQ+V*>_WX=hQtfX&a| z%_o?wWpW5VLzh?9O+P2sYcxQTo)N2ru;8h!&()aD*2wM@lpx1(7sUtBIcQx&U5=g* zdC~%?KL!>2kuDel%l#u=7%uS_;@+=0Oe%*KYVEeG{SRf|9oAH~y{#y=48o{@f`|n~ zIx0o!iX8z53@!8`B?OQXq=cq`9Yg`?p!5)GiV#8-5ReWDBovWONFo9W5CY%9nYlCf zyT6%x=MSFe&~nb%d#$zCdf#`ijfCWSk{_7)w4)4t=LXj%rP>cNLCv@S{3L&lH`{k! ziveJ)+!Ol*JFqcuB>6+AIY59;XP|d zzTEv2h4A2)?J$3d!S2(Rc-M#9u;4nn&xv_i^O^hQK8&7ia6kQRY9|jM&veK8EqOl- ztUE7UOZd@`^`D5g>PzG2JACg)PR7&iXE_68`WHY0JNj}&hb5D%1My->c(E+r z8{*BMs+2ZhSs=5Quvi~JXWbqu|_&=RXxa&$u|hx_$Cs z3Ucz<*ZxMKT4KDf#UvDJd%XdeTiaGejvLTG%m4g9_>aUQtbsq{GIMNSnFiOxGhMwy zXP_Qb$>K-$x z>D~7r*k~e^f_2?vZ!pSt%~Z_XI4|s3eo+8?W5UHSqrZGnDT5Y;UX(&=-meNt2Q z{VC|!Lyq_NO9C0UVh~E+$#tc&jcY)Ok}bV*w8S#DT_ko^HZ&D+(K{uwSjkhvH|LN! z_2OXl9j)C1ZHe9QPDb#&fLRnB3;X4?b_7u8>ik~ke%b5Xdop#+m{LI1lE-f{O>X+; zd`uEa`POREcGh~OY%9cPmIOcB3d(<(%Gn#$Dj5}Rr&$X19xNIc=i{w z6lc8=D5m*#2;@_#)PSW>EgijYVC}#?KbreZUomz{;v~=?$Rt2^+!S_juHWBN_H!T?mCA=ImU8*GB2j4B1{jWVMk~ ziyNKOK#Ez{a6n7qFW+;|@sj9JWEKuDM|o7S>q6mEEB!lo=(Ijia6VqbIuzAGUzz%s zMye>H&)$@tuGmKw=;~k!b#)+ zQg6l}B1$ZYEcQCNhIrc-Ehe}6T4Hw{6gV!6=&|oKv{?4b1lS;BGC6E?AMuJ!-yXhC z$EPk zU|_UTh9wH&sKn3O6>!S*4`G7M{9XqLde(hF7HI3dhFMnXf$^8fK7z>`(1+;en47-Y zYb%fJPdov~yRMk)kjz(AN2RO{&`yhzazQW@KCEM-Q1K%e{7qh8bjQwJD-_Zt53)O#_)qk4r(X>$HClYZk z{J3#Mak+bx$qR#rWUJ#2$@`(`r*Irw?W(6D@{`G-*Hur(#Yed>Rm~0hlYa`RjwrX( zvidHy$7T1u=YQnt&qcOt1r0loQ7x^uL39R&g=(4gB&JtZWHHpwC1U={r~tIyn4@aY zKwNV})j^9Jg zgu96TWQTy@xc!(|cvjxqZ;y?}wf=CFQUbiv0C*W#&L2++NG|7*9yBjJT)!8%b z>&vd5$rBWnd_L#x9fyR|qKZLF{$$LJ^OvlH&;l+}1!6}#g=g=kXaSR@Ftsx;Mq|qT zqM-WF&R80%Y+<+Grzt!==3|=N-m6z`33euklSbsSK?yxopFHulDZGC@!|%;%3)n8T zAM3@5g#oxxbS0Pt3MUIG3=W@}m4ngG!T0^T)zCAP2zxejx^N%m-Jg>G;+InWi_StO5#TD%PNeiir5g^3|G|4UTE} zACLAQSJy4HA08(j4JchcKV3QO)FX+alTKQib2ccMts^~n{f&3)|L4MiLVFLb=VQLGap7bjGarI-$Pv_yYExI1_b?v?grF%^JrURtJMiH;86 zj(@y(Xzd9QfO`)Xkd}Mw$EdqRl$|G`R1_CBaQiPi27EEG&aSU~400Hy>w^26DWIsq zZy4@kPQw0j`D5lQs>bK^FaPq@AF)00^45bEZ`=GDJrdX!$78e|d9oWoc>#RLZg7#| zH2e^fr6AQSA5`<1J>WEykf^A0?zYFV+=ze8z<)+>{n~Kxh3~gWZR=OvtpE`E3Pjf< zrcuh3tyjtD$d~${o9yE;+ZWSzjP$H<;jYrq0oj)>j&)KzE>LaCWm)p0z#(o7CLA6S zf%Z)lF^MX*L&@E!jYz-ouaOQ5-Z=z%wB|ZCFxMFq%|L3hiXnGFh z(`UVr66Mf7LMPNnWZSMFg?5SNjahL}ReW2Fe1)xojm`XjR`KK=g zpDE}^H}l`BGMBywy+Gko@COTYG1scx?xAyml> zCk+eLW9LXkTyO$+$#R8J`lUcPBmQIB{&wnoT$ORojbKx|I7h2bWXzX$^1JULE%EUd zWvB{Mkld?!JM(H$j+VK_2_TAjc5NYSNzZxsE+_((DsDdDTXESOx$_3;WkAbJx#h@; zq1l5$o^uQ9B%pAb>4JYY{{3d)6YONs~hhyX6YxC9stojS@D6$-5Tr{%%)5QB(@zEt3NMX zwcq7u>Vt^tc_(l&>S{dD#yw4ZQOegUThqvu5xI8zNK2dO#TzM-ThY8WW*?B#7zXdx zG~Nl&RAn5MO=)Ni92IOfaQdAdoxeRv>{;<@B_Lc-<@K!Yest8b_tuhc%X`~ zV7vx^!kbv!QA$}@KrKkUL_v39aW zfL`vSc~IuB*wL3e+yKc@aFlXFL3=y);!eUYY`N`G(s~uL z2*!^UR?Hiw6}Ujau$KHhSjhV)@y=&*4Uvw}nbY(rw51X()g-4Mjfur_V`Q^LNSel~ z`bgJl?&wEJwhEb{` z_aHSFl|55#5yy?fv|@x^miI-PlkpHx^hR_%XV&g_b#EbVJ#ygPnt*_kZ|hwYF;ad-+z(%%XX@W|TjF@j>%t z)za%bNXE>m|Kr*IGKP%s7DETqK z1Mo~yo{c3%C49}K4@vRa@=5B$VY9}@8@9K1Xqs10!ZqY3-iL`Ib5c=RBE6nia38#% z;H&Nqu9huKb&A92)Kwq;mxSnAf;K?Ln$MCilgLRo>$!_z&Y4h;nad=4;%)1U@`ULj zkk8tD|0}*1#Cgi>d!sCccbTq;v@*d-FRS?SIb!e%`2{{;0VhGp^r zBAi2WN4@WY06%vb{uaIkp$#t1FUHbaZe*R2IzPfWk;v{gz{`(|eN6CpzZMnx?B8M9 ze|MP^2TL-r*1xE+#Ll%m5+j>qgzT~B?2Ujgz9DP|mOG*>jMjARCfy|=3mcx~Mv+aW zz^Cc@<`&d1s1jY4?SM$_kzvU!_n{C*Oly*q2~D`zmU&JW7Qkl4pA2@18<1feQ7v zIZzndDYN7CoSR=J^-9|@ln<=Gs9Z;|ir7k0M!S-VzG5`3XPTpNW}|sonz@mB$s0(-T_*SKD7eb;XO~V!s~Pd)2<-#pA_a2mUxPKq7Y( zwn&exO)SJ{!q^+9CD$Aw)t?C~pmQ8q#;ZKdqdk9#qW-9Ojv}^$zL|od z)T>iVX#lnjKx)Nh?{_`1u%Sc_dcIPjfqj>_t_hHdUB5tc#UO!bQVEk-Z3~lrE+YBZ zRU3czAz7%S!?+i#@C&-Ho@~C{E#-nAsV58c9h3NlX1~VDx)EG0Kq7ur`IiDy;VqYW zj%t7Zq?NfY*0qZqAozjVK(d;oIy~D|Jgf^F{O0?b2clSrs(X8TQ{r$>mv2>}Hc)KU zCxLNr{vuBNwW{e;tOLn`n$muq&P=yME%IH{$M=aai(4&z7|__3Nb|y|NC)i7UeiTC zUqC5pY|XkjOCCJFHk>-4cT}R;BKZC7ph4uaF0TG(UyT%*-)HYXvoOFnPw!OxW*^cl zSrS}7p_!0!6AJ$H63*iUIowjb&4nM!xf2V1h`ujuu5<&rZ*W2inyVUH346aWoc9Z> zBC|7CHsg?N2Pp#^SteV8iW9ZGN^{dzOX6{c+@VCEW%E#RnD^x7r@G=P3B~>}E(+pK z;%_l746*avEIJD>>pA>R{uSmyT#=Fwt)3)MgU|d7j zKHlTtq&T=XU*4%JCiKcaLGDQR7ajla(OL^xRg3kk3ZoBG1#Oe{egyk722OWH)cOZc zP=Yx|W`5KJj3ge8Ffzz;W*##0YA0oX{n)#tTUzytFTvucza3M7oib+*^>0HjpK}aI z*X_tMjGcGxm5LQ0b{N0%$%Lg6f$Ki(7kGU=+5N2u&NWtKFORBkrIm93(qOUPqj8}D zIoTyC7s%tA4|TiUz_h#wtfc~_o=iAFbH4dR%>Y>^m^^P z={pp-p;w^Nou{587dm_|6PoJLDNU9b*1b3K?A~4x1FX-DN~g^*D7561`O!slPKkh) zMHiWiIGE7lW)9gbiShmBHFyEa(Mh-5_e}iI2_KEh5Uz@?%^2IlEW&>N`O^l|j~&;ltKGQeIt)bg z^wnF@mSS6aHt|J4-3v_#mh$&Ld2N06?+MEPe`S-k*R=M`l$1$yZwY*~9OwEbzi2;? zrr8}e3eJ3`CEQ@}8#V&V$$%@MrQ%?fuv-Chm~%MhNwqb)MQ**ZEj~+Iha&U|eu?Jx z?Ph0laS;vN%e+kf1>_<)_<`pcrWO7Kx$oH1=a01n8Qz@Fzuq3;uN@4@CMY+xPzT%wPZ)%n>g0rNI3ME1cS> z)+{nYKd7-4Tvs);U~~G^o}VH@jolgUg$aW06}Mc2S-o+%jV2>95k~jE z<&54L5`6jB6ezF&|5U1d<|rI|0(H)z?jxax9N<2CC3;suVI|zdl){Zcg*zfezjow1 z%+^y>huy;HZZ`N*9f&)vi_lN^#u&Gsv*7D5xmyZyzAk&geGCS2gEV@m$aLFaUqWuE z3HM>U;8%7~1julLF?oOUSN44Rk>8dJfQ+Y`X-h*Wi=oSsD(G5YLYL!mJh2b z{Gh*>cBC%Q_?y)?*VjHyhUaE?r0BYTsr+1E3dyKcclK|nCkhn7JNFU4M{=XQFO!(+ zwdJ+jgUlZNs3Wvr)|TvX*c=rdl~sefW)+mZ8`WmAN7?RX`I++%tkNu2iu@*0G~e&} z=|w15X=bQG&)9-}#O1-vB_N3r2Q=0}m@sS~o?CP$! zDLZZMtY&!FoBu2-2}`v!rSQ5?yNU}^4-UL^y+Mh<`Z|X#KIQ@K6FZdMKY(C}d;f5X zrlc)e$-yZ%OU7+DbIetwvIGONX7N}A_7`!wFgzGPd8gSftJ=96M=!XcKAg}CZoKtf z(Z;f%Ztk2&K-gSH<4=Mm*io7l7)lC{B;>_$hCSq+BF35D<4)s#->(Dcv?JAHQi(Rm zh*I9Z)CXU6CqzT=o7%{dpTgdsj=7ng9Z^3n1r04O!_2avHA1NM=lkn&7FJdryWJ+ieAH0xGt~P4I6Sqv?w!MHjQ; zA6`?VfGk8;Ol5x4QH3=KKE|Tax2&uz*i|+jA|fKOw{ygfMc)h#u1+2;Y_~>1YAyjS zbI*u3HkLhDIC~B{_1PwQZ*sB{ioSYJpX`PFt77=1UEf#3N&_;w&9KKJqob#X`718%%f3oas!sGE6 z#;X!#L1PPx2?4)3VOKbUx~ys>RGF&g1oVttzaQukQ0ua}4qB4^W-23vLcz*_Gpo(; z!G!0X^X{0O`ppdU8+e~ih=)A{EfCM`dPI9=KHZM}xrW>o|2!rZ=J7$gc~xo+Ows1BVlRZauV1wb~{lyieEk_~&{X_qS>z!V`3(M5E1)L|1C8 zkDqx!B_%7jS}z)teiUUvT+mr7QwlT+@XFHG|OlY;<2DIJ`v0dN(%bv+-F$qz9zybQdxc~n!+&V zfm|<)ds^~`ciMd7ezzzf7nhJ4h+UtjZwjY;RvTH?^q*gln9#CfyROzxYn>t?R;9f* z(>D&tu&&E-mKwiTbOyDi{}d^3t9pt|os`hxjM}7WeHEoTvDPosKP*z@3g_k7z)F6A z%AwQK*Y9*_F)S*kr)y$#wb)lx*b-Wmx^f@B1cmUcpu6a~@|>!58iRK!(c_>%UiG*z zuF}(&UhgroAX_mz1+hHLZfQOi>#@;^o7_)h(dSqE5UdW(u?YfcAvbX8QoA||zt-Aj zF~g1&_FxL`ZeS5umn+-{!9oLciW@0+Nhp|&AJv6G0!xat&iVI#83g-K>kA_%5Bmy}160V_8!(B&w{W)RH{%eZLuIja!A93UuNf3TS)bzJ8~(jf-x* z(!+1ZQpJ^TTURo%lpEckvxYgH8u2wFOq$w6jeN!3WBwCoLyQ#^Yuaj-xJx}Zy61a@ zz7}(uMIDwCYK~hfy`XPb4KYkS>fNZfwIy^;$9=3@UF7B8!I{8N4IvSxTX~q%+)|h_KyI{;G@`)2vj~=GGN!u65*jIyUo(B~iJ+uY zDnGAFYU|^Tv}a^SMT)lXM_xmG31(NJCG?x4u|J`Yq_T6->-xq* z?Zcwja&RfOwR`tmq21!h@W`|)KgxP_jLYb0Si_zTXUF zbfEk`#~x%RGCE6QSbmBZf)=i(e{6djr13yCAj{-mu;rHE_dBEz(tmo_iJ0;Xh$BJ3wJeE>WjcB)!x&A6otX$Ki)gx zPSKCT61d4^%vZR9c~4-acqZYoz$I1f>B}%~p%J;BR*GB|EYl6-F}(|2o(V&i&;odz z*yBPy02}}UxTxw!5B*mUw6u{jAfp0lyq>BuThKP&g{NB*H^X5|p#p5RQIDK6?FBx= zm#+$Y2eT|t&um_1#lFBlB@J%FZoK>+tTo7xftctJ$x>^fs_l;f{rejJMu^`|`9o&? zuJU(i=HVp@n81opm;0GLuk@%4SuGoym1OBp; zOtM^RiEc}|=}?MAqJm&ST?&b&|(RtMv$_K&*?%iHc|64A#sH0Z)}k5%-( z?t@#c8crymQZ!ueH7r+^>PGvSig)Y`j%LW0%u&X|-|oUH)xu6(;Bk+#yZ~wD#9+Zh z03VQ|2=y?-$pI*3camEjOeA3Z-j~i!@5ZFUeHVX?iq8O%wj@jKWPkQ%5u~<~B4t7a zsk*BRW8rnw`5-N4f}byyz(sNq{6Kt4qWeAHg;hIfej?BYTsUmzq(gl5PF*nL<;s`~ zNEZ^}%5x{MVID2#cga<_a`dd~XY2@HA#$-n2)#d|L4JRO(C^^b+|B?a9J>M?CAyyc z(V|y>WFJW2a{_2|nRz^hpeJp|PK^j)aA=I-iHV!9Cq}F}Rh?LgG*f!9RDVCXh%tv% zNhi3I`y}nyqRy<(=Q~@|H@}hUAMk4j+}fix@yDsX{5?Ux5O>u)N~3WerPFfM5u#v+v8SME;}1n2cmZ!HF#TGVfE^*d;-IY(<713+i@aamFi{|)M&ER@F6MkqKwVoXwbJJ8qjP)Kz&i_ z7r~;{nKS&U8O4tJZ=#FUI%P!zA(Bv6QTVT}4*d>n)^s|@J{VH~*;CnOBB5Xu)sy1$@B z-(md$bI!pg_*A)gaPl}54+3hMxR4`BR5=-J{yXCwdH2iJ9fK8dv7GamR??+hUaMf7 z-K12=UCo6jKt#3Q4SM&98NKu>>q@zi>P5gwL<0MBCj7K^6qxwaEYIMJ^Jmm*~%A6xAy8+vuUwRi;}u~r;b@nPuJ+!N2NvwNC~9;w20VH=r15(gYN$uMn%HJ71uuX@oD7IXmJ&d^1yrX?dy62>>%dyZkP3u2 z2TXlF0vu7|x1vP2?E-e?U(PnbJ8)-PcM?T4@C77BtuUk&Yf_D299Z+E~XuJ02i$BEwk+;6Y0Qz;c!6b5}%`c9QR~0l( zPhors&B7+;WQJ{PYg_oLuP;7)A@gWyD@EWFwunHmY;CRbuKGR)ourIbKx=c2aY$A` zK|#T;s^JmoGz9U8(7w^l=z3s1uzWpgwvA&`ITTpw>g&P1w81=EU0GQ(7^NhS+P>P9 zEBY$V#PTFf7)Ol~0d$FBpKF$GC9Xx{Zld!hN|>EZzuW8oB_8;}E?(d&T7%!ey<>>8 zNqdm~-gTvWL-TD}L6LxAUqO*1=v1XGwiTINJdSMZa_prtia4%{+ zF1Eqgv3h@l z6onH51(}&=4~rJQYI%Kn7v9}khaK>ZgH6%Aa`r6xnoZF0Q@JTYvFZyGM(+Jv=z^rA zak}%V5FAHTBcZtVTDZP+`S_q#I|8b5(n0-{&&dZk3=AhOK52^{4@EoPs@ie>rn0r zln~B1+82O&bOKJmLY(8AWQSneTjsm!DefA{xdc5nb?5kqs(YeniBFpwf`a3bb#^(S z%M(>8HN5wgGA-Nw%XCeRQh8?Eo!bw4&AX(Jb^^6l9M;kq(lD5r@g1PUU}Ro5h&H9b zoqfqoD@){2nQz6evIb>Z!0?E*irP;(!^+qqn0+SwhKDG#N&F~t$}v}`qIdAVMrhG{ z>Y#$(5HpwhVNy9u7|xZ5j(5<9I8LDj!?6o*UgG^nK0w^JyFi*{M*|V4TB1`RrGr76 z+{1H=y`6g8g5WnmE&x+1m925U6o-ZZ<<1;$9416q@d_;>e|fW5AP-xDiOA-3`6`>z zxCS(^7OdA@tpnFjsuNhL=uPY9hPAJegsMziSCcR;2x2rMo94)qObo?vXO)9jA1=%X zL7E{`C~EOEt#gzZiA~!-yf%X7Y`(Qw9#M&O`Q5Nya9vl7(eR#Hs&#Hp!gy`?Pw(n| z2*97rLK_^Egi7c&2ys!MMHlw22CD=TZ-@ANijOSi6m*I6}tv2GfSG+~)B?G6fBcvi2oB(zR5f*Dam1){4165?7~ z23D(2L2GUSXQuhPd5h&WmJe+qW9SB{(y2#Jhc+co<+@%&m!r;VQJL3>E> zhR)!(7sA=O`3(qxGf66z@fLyjH==&A>=Fgj=6f~&H4ugGl=(!v{OLZb3Gq#K-rN(7 zi$(21$>zD#QHSQRdqM83nRCJc<0GC77x{@nKatd2ii4Y|z!xU#=SSKwVV*EozCO?+ z^TT}wo333JIwL)=-@Fl9j`ZPa)hp#1%zPV}^mdK4@c?Kh*x)Mrze9e(x~DKmK^^%-Ji)#}H|f#pLX1V`n$ zPF(iLzB&baiW!d7)sCad$e{S&6Kv^d8nR{;TV0c;GVdXJWEiWWjbh)oh4O&eCtS6B zQd2$JU}manqo@S@ONxF-wKtI^4GBB}mA_59+%NEy`H&>%3_IZlvZ4CVY--K-?IQG2 zj=Y@fe7&)Gs<59itjo7%cjZp|NXU`;;?Uyl)H^c5c^#-&k2cz99$|Ww;y8VM2n}w- zAqLh45oUR+e&)@zO|?I@oY^gK;a%8#<1+#7>-g~wk2dy5VCEqKfnAGh!h5HyV3p-L z*cvcX&7ZXXMr@39FgxlSfimNK$NGBek2 zQ|7|bpi}yh=OiN23J)$G!Bcy1sVsWo0pI)gUm;UCxEihFZ6<|pvULR*1afe$_5HfG zNs3>vj^^6JCY)L|jS!6w++a0((Jwl2Q;xR!4>n1p`@944?-fTA3)#`NbV_zcM(t_K zenw#MhOSCAD?~u%t?1{qDUs3m^3FM>eF8_vUO7;YnfXn(mo3v7x@FndwFaI&SKBZ( z3jlB^b*HdE>e?RB*x|p|N&tGc!~7*S_F^@)%Tc#8X73;ep!|LWPmJ*w-*H0k$hl;q zRl_ilm=>^@F9Rvg7bpemmA9$~U8@lV>-VM|r8xoM;PU2fL||Nq?7&qt z@|p*m^ID*(-_0GjaXnCeg}@lC=N+89quj?=2znAF%L5&AP0nn1jH}JD{6dbz+9}Yu zKd@3eA}eKQV3(l6mG^buQPIB2X#17%x~?h8W>uz&?Kr0}c{o9Es)OFke9iLq2}(6cSFD0J+L$Aa8G2frrJBjO;$TA1nvviW z?q>Y*4!Y>Zip1*oWtCmc>nqKgN1u15s!8O9B1pW!VhI*Yd!NiUESGm`NLW|Q3Yg*H zmH=iSo1QLjy)u;TwHntpRH#xti}LE{PiV={O%c0#^=jGu-qWS6V_PW1=UxtrL|EV{ z?$!27wpbgKuWa-PY{pNLYF5ndzyKDa4Zd^}Rn3Xg8etTKQ92uDozf(nQtl_QwVAbA zqCQ%poYZLU3Trrh@O$*`V?Hc;gDB@w5VJ?u0c)&-C0?WcIXjKnrN01b#8<0+W`$MYse@SHi^|PO{ zLw7wSlsK(_N{z^|Av~?UxE-eT7N!F-gPc*DjVKM=F>=w?4aPlK@Dm&ScvyMRMP-EH zHLR&N3eggtXOh}?5r$QZzLpxxGNWA7j2S*Pac>?@3TU%8M)S0gKHhl&`eZDw>=PoNUU)CX&$DZ9>7K0Hjflu4@2Jpbg z{uCik8Gd=Zt4#0998&IeZdz~?x4Wzu44lBCZ%}1D_Hhly#qrzmXQn^+E@?8m3c#xl zC2M-tt7TOz4aUA4ws6JQGWkyp(du(ASqU{8mW8AEa;YBciVbsw%Uw}ov>j{xJHMRR z$mj`L&}sd*d@=zP$mmJn=vspN8kWM~qwek@urvf)JwjMfwT$xg%^uC<;pJg90D-{9 z$p?|tvM?CEA}gjNjuuiqN&C(o-RJ>VX!b2i39IM_ue}!ia3>f7!Os`wzuIIyv*wFrbAllb&F!ETBS5+j>GSAy3myHupycq}Z$m6BkMS zWL<;q zx%LReRLCN;xJ5i6xX3`;@1^mTH1!Hx06d+?>ojmC2w*ym@|H(-CV2}y14F8pp(-s| zPY!xJiS~T}Cu9P;p&$2VI05A7m7sTxqu^T-stTL*j+g0z1sS#(79B(=`wL z(^v1ohs&fVGea~^j;_*K;%NyaCx46Nq}65lkkfvM&Ffyh?bcLp8PL0Q1TnFw5)DJM z2(81fz*KjrM?$j4YGpEq=~sPyV{Mu}0kDd2J1tPB`f{H7+RV5exD@9xdO|lr?mjE4 zpukXHZQPM=dNl$Oa!f$Z;&`rbC$IZlGs1pKa@Y&@H|oN3TH&*F$aiF;1vY*Wq9C_C_XI+Wk6O?#(>C$Szywp%Kh zDa(WkW&sI0NQbQ>h$U`ACu6^1zOTNX}Mv;v9Vt_OpZOO(9qC02b&7QO?!7}>IQF=i{g2&V|;z(o~uKrZkHba z9;S-CO8{0-7Z~(4_u_Qh%0mBcb40phdwYA?{qcK}#b>;y2%_;!v*nC?N9q1FL`l@f za!J)B%4&I0xVq}L=C=*jJmG0FeP$-69fED0YKMp!G|Wt$1+XniS=m`Xj$m@4{?d(x zgS>66NcmSU+tn<4jY^+#nSDz{Is$u2rMlm}XDxoWn{NGEiQBI%;2++!b(NtN7NY+B z?d_i1j#mdSw2*=(U$s7C`pHZYKGfQpeA4VXF+XK~)fotyX5w>ZQFmUDNBu5c3X`!c z8(7|`$~=}72A)3V9N`X%5d~BqQ9)!!N5>y9>vtxb^3Ago%HV9wnXq=1--9YGaeO1p zH3GZOf&gyacbBSG|FAeFWFxieTb%q&6U*{I$_JZU*;^HNzUE>O(5UMtACtnr+h+S0 zbyDcT!+qMyP4*@kD3oQjABoptte(5fvo0u66On|KIV6Cz+el>uThliNJ4HHxW1=RW z_ZkTMDujoBO(01#uxb6 zwRB)BPq&{zR3m>siPXlUGBPx6QE0ft-DXaQSs*GtY&|Sd(AG z5A1t!{H8wtzgzWxAD3@CHx@qGpK}Sq+KBv7b*P z4`X&D%vLUD%elvSTUwD?;vx`NF`#R-i9qXbeS^w@hH+7={GI{-@IFBFK6Mk=?R}#X zl0x0i4bbg|-kTm15kPZ9dZmW@aCknrY-SFUwYHRSQ>^AoD5ae5pAI6R)P2Z*JO)u> zSEwZebWx&}t0542kz*!S#^{9AF|A^^dSPdN^B&@oL@k@zptmMts#wmFDr zD5$lT@zyeOSTQ3vPCVkg z&k|VGqv{8zJel+EWywu+uNo3&P?GVv%DXe=;_A3c=Yiweq1(1|?cBo$Txc%}@O^S0 zA$88251aIM$`!2MOjR6p3Jjx%{q!lRi-bPMXQ(oNT!nDNzy9}sxUd=D zbEClhs7c`PA+G*@mlkx(Y@$bqh8})))MfHrTt1j>oZoqAcXqcmTYs)A#Ku?>znpXU ziT&22{SP1i>)%w}IB5q>h&OPhKHZJ0esY&i!~WN4mtT<*VYXH7R?# zCeYYi6=tQ`rT>tf1?wcpERRq_`zm#sbJQN3I`t1`fzSCB7uTTd_cCnNYx7cPTcJgy zXtqi4IsqNj5qq~^HM{72WN!Dgb(}H3IB4obk^trmTCZoA-615kCN`~Kd0_?rNDJu8J_UZtmrHk>?Nm5V&v^9HK{Pnp1av| zeg3oW(9=lXobBHCa+Q$fb7oDCFf0%o>(ob^n!q8JvPCybNRwk zy}keFl?v0fleIW&5>(u7$iabHu6}9btcwO3v1#g5kW1ZH@qAT~J#LmP2je96_GC7v zzu7=E6J||n*xr>JO`Cu*+63bNnF*w5Bb$6l$+b=VrWiM~BsfWLw$#YrHYg1t2`*(iq@)Gj7h+}_IT$)4@&>jNCH!YHfsw&?sYpC7N;wa z`$T2^BEhp|&}DXMb@jd)4=v$ZdZ7OtW;!_Em%V?r44}&Nluz$I`A`g~11eodw9=ulcWg&I<;M>(xw7p}iJb`w9@qK1OO(4y@yYg71vlaWKXeV-;0$ z_Mgqg3rRq5bJmxJw+fpBOZSGGSlu>A9?27sMrSt7?L#Ub~C|sut$+rl-zrMIyEi+_S>`qq><|=4l1;~ z?2)^%TjUklXKv_r=jW1t_$WFu8h-2JG$9RMi8~$y%{;zLissb3SuXj246t}TVO1f1Ab53!}Y1E)?T22p) zGMZBka3Isyk%qWmDA~p^ijr4!6F*?-~`=7phRZqEp4y)PdNOtKqaOXTFruiQ!k zdiT3beg$%dDC7K1+v{1dYOi3|QG7^&Yk$GspZfTIN$(#m^v4DBRALZJZoyoqv_RYU=U$B5qxy6t=6dwm53J@0nquty zlQ;tp%?`6cE@Qg(hRaXikm1nuYe5^&6(>GK=O|lNy02Zjc=8{*=>E2VQ-r3?pYf z>)5@8np`VW=ZO_8GYwFYIlB_(x8>r|K6jo_!9y!sjj^mL9QSF=t2M%^I^EnGPGnW?X7eC)!)Og;{c7hjWb0Qq&uE{Q-scV*KkJT4`0>5^1a1W)+H#WUis_)y1fK{x8DDBna`faj zuBEm>NH&wT)E~e!js>An8IHX}r7k@uJ$t`h@x!^nu@igId(0QI@aEa=EEQ?! z(htEb^`Y$*)v;3dY_Lx3my_Dc`qW)Z&(XJ~g|1zlTRrW%;z2*0yL|Ga(M})F0jw*g z$fU+F2<)3YA9|-a3YT9RBowUVzu0Yl8{4uQrxrB1M(!$HapF+TJ!dVX$2{R&tJTR$ zZ_jX*09rd=5eW=6Q*mI-*PEv6jf3s)qC3k@_m8caNZv5d*?Cd7iLWk=FuvuhNla;A zbYMom(Xvx!f=i(T5uvX81Q2ct!(LDmCyDMP==|PpTJ^31W9N|{W)WqM){DEE9Kw>$ zm#L8z2#n>;_~KNB7(q#?3Uq_;@lKVR3F6GKZy!v?WQwEJ6&%}|x)m?Ef8JztOd0n8 z5mpL-0|rWNrYLDGC)+c+I-MC_^{W%s9r5_`GzBwDf4Xf1t1h|tg_4`|TB=OQnU8ie z8&Bm%Qx-w831CC|zGC}k5&wOHA+^Iep8PGu;%w`K@(a&v`q9N13y-E!>WD+S1t-O4 zgyYFrSUab??#cH&k^V^yO1u+SMZvD7?s}tzv`N9=4!(9S(|N}6V~A*4x=4SYd&JJ# z-^nYR5Q(>Yv5;Q2?O`(!iSNUF!2>sU-o|iNY3hv5=CyjJqUTh~XZ19UdTroVp4x^v z3YaH4y)FzlaLQtR=*zJ}aV5GZ5U9VGhV*2nwh?DyUH7>z|1r!8(SFC{0uTCr!E<10 zYsXLG!`giqkiCkBaxx)z8!d~IRx-;K@2t-vPCf#ZOeH9_4v~IvLLeAPZ_pk4J67@@ z!h{}I;s<4dX=zHgob=a&!awQ=EktsSR%*(lAJ}tI4u0mONRmZqWMdV*1{^vA0!NQD zdm3^%r6I)3cMNnkqh8IIkucgYR%DK5?DP{BGXypj?Vnd8+J1D5yVP#b^YH!Y#e#Pj z4}@?-eU7$ur+JqO)1%4lYE)rN!D&ibQQ4$S$gJ~h9h+`jROR5CWnb^>Q2oO0f3qS# z8K)GS-n(Ts9w5x7D2G;O0Ue!38eOuM=4KkbZGUy?2@fVMD2N9R&w6E#?jC>RHGuGR zTWiX^LXEL|s3Yqy>`T&zm;%>B%ezsqik^VptJZy?gNJ*h=dSAn^GzwON73s` zXD4TmyQE(;+gG{RHhoycTB;SP9BP%Kh-iC|bpLsc!_~qyGDSoq_zB%7Q_a;Yk*+>? zJ6o-=d$scVZwM7hRq0w+RktDF$0!E`&iKt*6w-m7#DbD+Hj7uOP}niz0>W#)*qo#$ zSB?ZbWvMkU1;qNR)FG?X)7|kO%V+A$G*x8?tuaWw55O|G%bca!p&^2C^|%+8s3zTy|fh)hDYth)`Io z)TU*9wACH`&cWLN&$~2G*^DHM^)b`T8&^iv_hNpX&*b)a`0k`<=S`;@zOBA#_iXeX z_Ekoo+jJB1m>7P8+DVG^dS0C`OYIWQOlynqdeh;2TWhBc^i61**ru$%%T{m&b+|;*~ z#^0^@gmrO0RdkpoubNg06nC6t+9N@!5|caliI7XjtNAQ{i`csEUmLPe%;VbAP@SAO zE!z|1VABl5HtYJ6;bWDM@%tK4@gLNeL@!fz-=N2r8;YP6_SQkaJv(}`qVrQb>KLJpN~UU-OFE}o(kio|a!#C>Ja z@{{%LT%yfX1^WB|J}}N}T4Y~f`oO{RBQt78aZN5sx1o`=p=VR6-w7>LLFoA=@ri0; zSpgWML9F!|?-fwjfa|;a>5yjAi_EikKcAYYB@E@Hb3(tM#^!0D`}x>q-|LeZh-|x$ zPb?yqM|#Gnvq`tsXB*9v4d}rw#9XF#upHmxMo-H(A$~UN5x}A>bx$57`^v6AVq6|dBciR9~GV+umW{ z_L^<@-n?D%2YBK911Lk-0F3<8+SudMYcQ&T=a zyOmm-ACwT%2o9~N1|P0Qa0#%kz%dRhfGBf?}tR8bK zMo739h+&qD@27bx%d$ExW)s|iPk_+Ka-J8qwl^GXnE3xBGo z!lyW!HKMk+^Mv?BwBD;peqQZY)KNmb1>4_O*+SAJQWcS#750R!Y4d1#UtO=q#-z8l zUqL%T@QV7js4H+#`>350^Bxjc6G%N8nJUrV9oc215gl(==xnPC2pTpH60W6KL514M=bol&gv$l$aAc?_%#6h zJ;&S%23sJe0&yEyl)o3Y3jB-@3se)^&E`;fD5HQ6c-6&XIn+o24FkM#?~M?fH;Q-NG_L#b{1R-7#M*-@%_*VY~O+E?$n zg9&*K>4NbwzeA#PzdP*N%~9R6(A7F4JR#}3*FM71#gk{MG!eYCi^M{zYSg- zUQGmjN47_zMvR_B?ej@^D&G88{iTg|W{O2~W^VXI6|3Zjf?BBzq zp5OC~>szdB>Oou2X_#px4KV<^=nw|Ryw~%Cito@{?B(SDUkd1F!I7b=06^G?FD5I8 z7|modj5i~;H5@b_Ynm0ABXadejfJCX)p8qrCwr|{-S=1G{t}}Ju(JW;m{v2PPZA)X z8{*#b`y;3g|N2BcSm_8?Gv3$4?Y%fr08suC(vbVB0C@QS6y)z!{GxnwpI;c$4ai%X z*G--FyGY(1=Xsp&obkv0Qqy0CE{6}-h~^h6?K86#Y!13#8Ohzd}Wn*Bk_9{c*BH0j}` zDL!Z(K08r0-14|s_|#|rGD=9zz9!qu{Jq(j=syAiB~I_l%4CgQ*LYk=t?1kxNZtMt z(Wi_29+YAy?qfl*ZmIq5@L}>{`}#J^!0Y?^?ZAtt)PNbu>YldP=Qn!9>b{bE26E;NyV$(m(eRuA#Of=*0F z-JS93cLs=y$@)+*7@XsHR#njnN&j@96v_;(XZWlgsdYo&tR)PX0Y%GTx6Tt6$tt^b z*cR>rJtW}@AAse(EPK>_Y%V?isNndJk?_uQfpw(R0i(D_R4QylUAmL|Pnx`4<{n3+ zL0qW3nT=%~;T^48QPnrf>YPyi>Gp|k_UdINXa2=X%dLfT?dSfjr!pj~gOc*q- zpV@4}jI4OrCnS9}6<|G0t5_Bw_V-0>7Inb|Lmt%lx^33D@XoKDk~`iEkhNcrVCVkm z@liY$PM=U&S%tICOKvm{alBT6f@JCP_9>;K32-eL<7Je4vP8IHBl5G!IfJ1P*7KXC zFci{rSIEc`1!^Y}9lhxVUoFRK@cs7y6fL3?MzJT#3Eu|rmjbw<&W5`?H;`q3x=x#N zNBFS7Ex}dQtU+bffYGrpYf6gu@O5UJp&4CUTSLL$MgPsFT$EWKfO+@rc z@W{2%akQ%Ay*)u98j7QzLZ9-TKa6Ak0fHft#Nnulag;w?&8PR1*cq{(6x*z_Mqfg)0W`a7`i=$ zIs;7~Z?-H>lbISAlC82mJP@%xRbe6ZqbMSC>)t1E2sYi1MN;tG`sV^&8M{|Qy>G0F zKK?#%4n}7tt`yB~R6NKIorwGFY zM}ZDT**Zlyd(J1?{k5~fl$0GzH@~*Co6iSx*LjF-Ur>wbgJFXmBFHNQGJGB~EpuWS z+nC)MEGYDffAa(vDI@9p+;TB!{qlNu}9HrdAdow_J=71}lS|*%I z{if8q3UEy`+d9c1!wxi4lJ@GyC~y=XIGE12x@L>qj7^8NMop^yTw+(au{V?!>X+@U zvN)@y@Y2sU>yy$H!%+A_`@LfM_m%1=V)Cx;a+quHk_@QJMJgpBXS&Fz1mcOUanR)(xmKX{Ox)Q`a>t<%#U^tvyf#Af%j-^Fi7ow)%FKSASs(qpuG~OixCoA6rKh@+;`x=z0TjgvO(2k_g&pl9 zz83ptX?XUp(E&0Ur{=m^$I^B0991LzW|G1DU;@9jxi*e7_Q(%FCdxfEQo9oFb$euq-B@oU+^Mcs8BJ-VM7&F3MZ`F{i17s_|>9uYEN#|MIcbf*ZX6t zrsqt}oZqAMxQ}EKpv$@oX$yee!AtMWlAF?yyj@G3+W2PsW`*i4N>?YG6Kd3gr?yh2 z&7rL4kE*dhhdk;GV>AS0Gj)6;ys${8>YsEEOas9tz!O(cTI!7%+9UKm!!(lmgnD4C zQg?E-$zQ5vwtk=|hF&>G4q@tFbj2&RXS%svnF83oJ)LbdY1a46%ae}a_NFO+t9CI> z=SLvj$CNAKcjbO_AIyEjpb@hod?xjs8hxh8+qizjV}hy_f}ty4{!~womw6qlWrG4i z@5P=}hvs*z$+>hF9v8gi+Jm_D?C5Vd@*B^-vv+lonQ3vXytyAE|L+j#2~FDaBNZQM)*0tZ^pgM+Dovy z@kS{@*w9r->sk{y(fiaao9@r`>0PR4T(hP(qC&9SJr#`5x+Y;9(he>pMcRE}q70n^ zPK5v#v^UfS$AO0UP^Yu>)OjaD`An1y<{6FSXtaHXxi z`tI=9;EUG@O~<2QjA;S|ZJX_K7%QFN_#CllC*X2F1$q=`XEl9(jrn5?jXynj%oV=l zYvOA?T{y{VI{t=yi>>NDcnje8Z%Lc@{EeH!``)64KM;ZUtYvJq#ec;AkQuv&S#$m8 z${}VtM8OR4p!qT-I~$GJnR}NqKPG2eDZj3&lO}oTX}c1V<;6McV?7}Yn|x{KY@su3 ze-ZF4{DZot>^xfVRzK|)roys#29|m*cYSO0^SGz#Xm)c@ErCX6A!njzE$TPsaUbPs zC{dvD7O~l`dJ*kMVbx`mq}S6s$w5g37mOm9yhDsYbao>i_awMGCj>pAW{ax__O~5` z(A#aj`CWN0y3)4DYt5qo_uUo&nJ!~V*w=*xtVk$Mc1^*fsV`VFFEN|WMzyyX&uU3M zm_vi24829>x32V_$288G+7m;rnis&q>0yg*XQdr0UDPdvaq2AVXFQs=xs>i`ja0bFZ3Ff|P@!?G*zTk~ynmOMcis|n58iT- z6GZVXRHnX`)Kg@lIvYYlY7>46ddCQzA6_byKNYrP9{u;RNl!zTTY0`t3r1*a?}m*N+(QJvDJ5 z{+IjD<@fl=@FT;0L+;rTwfSQV1O^4y1W=;rt&sr4B#C<|Yl4d0yY7$4Ro(tZfRC{vz)BumnPrf@JwT^>=$0SGduX z9=&U}pp-p&%SjJka4#hoTs7T{MauI%7h*#7csIJt>v&3XAxkS=Wh`1HWG-i;iNKLB zX{qQY^N^$0>(FTjy%GcDy2U3Pu+SeLRuC9&`J{Tq94zr!`r!8Jv~*73s7YU1ML2o7 z0_Rz`iTLev4;c(u03qJ9JK~jke4fonv~IkW2-~gJ`xJ?0^A$pA3;A{6!-4P!h4Dtr zMr#36BC4RSN=guafK>&yjdc*M0lUI^E;~|SsISk`Qi($>GJ%qQ23ISb+T>p$JuE?6 zkb&>spg#IU{QQGE7X@5`Fce94H#(f}k0LJgfr}w+Q0}QKw7mHc(xDYiKs^TZY;jsg zsxTam#zL`1DG0JNSeT18F;z~6tI-QwqkmK!3LpY?g-zC>NaTN7wSJ#Q* zow|ItVkH9~mNNNZjD9r*W*d@}Aw6b_NVv&oK)r@kyjtp{zoS|hjTaP{QOrFc@J+IP za1viW)~Ljc=4eOL1W31!Nro9BtF(rybk|cH!&XvRuBqfi+yZOh5-4-^SIcyoT#+Oc zw-UULh;|~Xo>G(?JovtKtqwY(ZmdNI`r|5gd|sa%F*w+UN9Wy_z{uzN2Eg7n_8CT2 zS7{OQPa6EuPI=$B6pz6>zIGo0K-24!{-T${>A=$@MSg~$(rt?nBidQoOTAx4br%|(kYPqS z?uT=@Tcj+n_8Y&$**t_E{d<_&=0KmWs3_RAcw+OHWnZ#zIPS>Hl1#Aexz;902-dZD zjg#?D`zw{gDQk{yZkLHz#9hv#n{C4u3phIqPR>XMDaI7R3RvNu!87HH7T;M~Wi6aS z7vY-lC}w*5H6bpllz8L~nUgxU1>I~E<-Ac!Vg>`YhN`tkxj(seFW!}H6-#}GV2z+n zuauGvJ@DFmy|SU#@0TwNqFj)yVwc#Hsacf)NWBE{iI>TGYrt`w)gyZ_+iyTt*d(6c z;jn`A@SJuzF7gvHl5nNDBv&M+z1t>Z5R%CjOl{8J8G4G;^)=9G_eDX;AHC$`?}i)} zBzg(lQRh}G;p=LUwSy7shoQsg|c|3VV|IIkaoh;LM05KqWfDN(_i%GXFeI>Jel92KYs25 zn1$9;v*XuskU33Fl+B3l#unq?NBr!#y7+-HiegI}06ELX0{l&ewPZO$@Kn*7yB-4F zNlX|QN*!Q!fxfIeq(4Z_(+P2n-wb?S{YB~^98aL595#Bte5^LJx~T{W=YgZ_L+18Th zo9%B^T;&rm2n?Bzuyuvz^>~-(?hoSG)am?Fp~>!F(6!&fjqDS+neugFH17xfJnSCx z+dVaK7OruHUX#v?3)}K}?f&>dapOA5+;LrJNR?sot-USrtR{$WxJP44KAEW(jl;j~ zd*VkA-7(YLc6_}K+hL;Kc1&%BClVVMsk2LN0@>L6>xgOIE2=f9B>szA1M%tJxF!L9 zMUb4gZm7!;C6_6w_@a7oApw0&OjGun$(h#b^(6T)abG~s8R%iA=|j+j{MC>x@LQ#l zUBYJ*3DY;lcT8tpQ%4u06Ws6Ag-x1x=yD!iYkR`4lzobblX$gb>^(p;v|=hDBjd36 z(_4#58mD|+46@=DtvCz%s`4{?5IN5MF24U}7o!imm9C4ENDAE+h%E>UH~e|1e`gvQ znkygy#YQIeJ?&+iIul!X_DZ0rtuDLNRUUyPv1(&RN3nU?$PUf!FKyW%jRNC`wIvDS zsn+=&UUf#;t%iH9b39qb_!Sw;V#4WrF6^6KHMx5@r}T>)QCc;KS$p9gGmuH|>thc{u4a9m0(XJi|hm>L^%OFwnd7&HKB+fuVRs z?iFMNuHdUDLHs&ljJP^E%obj>!(!vp<-bBk3QY+*kcoPqa4Ul(em5igxpE7(4i(nF z4k0)%Hg#_aDuB!_Yd$V!&HyUmy{NRj!LJ}*<1oFBdJAYcc-DZkgSz)>^M{~;Rf`** znWYJfj+5;kIbR~$BUcq}mB*zP+TyP)ggN7$^@v*{Jr_v4a88)Snt}~WE;0be5ani} z@4VB{_kH(5Niv%CHA=EtS$4|gTipkRgBVydr@Jk(ZEABR8P;?v3Ebji$H5teE34^T z$1ms2_|tcB7h(}nlnz#HIAEPAtZbOe>sH3KC4ZG|B(*cEPE_3kyBs@_{hHs)YElU? z?r8N3Y!9;v>z!{x7TM@2oj(^jWQ%$m$7Hmdi02Nmhwyam>!+9VMmL3~YuRz}L#FF9 z^_A7LKn?G0lgdKTp}*4>+~!;HL>M(5i$^WeLnqG`r|IEdWEik_UbbD0NEEMhz39`A zFb+l#9bdoq7l=##W%oD}W*c0p<;#?E-X5k7z2=z6Q}zKz2#VK`X4yQq)8y7wB&jk z?5-%0QQ!EZx6*a;eB<0Lqu=XrUNb>Ru3sxKzYLeF+s;gXE@QYzY)=0SWno+o@1^y8iJ9P%`e-vA1GY{pQj`7H@Q5KQg{8Jkgy$8fg`mB&5{! zHu5?5(*f_3@dQyD*4S`lA*=OV2MVtM^3KumYxA}|>?R3YomLAGmkZF`)^i`qv?PPh zx4y(mxSu%uM7zt1d7@n8YYJ}2UjX5!g-#jqr~`WccUQ2 zL`<=HA`wuR38O7x0fin!hCcsnPrS4_i2VRr{>Gg3P~>epzmTt`UKaV#1O?4Z(!LB` zUA*+R%2=;aV({SPmaPg7adg}|B#QI&h&olnkJZU~k;ALhT(doDmw3|c=g4yppphxF zmH`$a&(R;HiF2m1FD_tg@C{R2Kv^00HJH#&D~^?bR;W3Fs`bjV z8Q1H19$o*Xp+pS~N;>hqp@^L>=?yM&nG;Y<_HOYQ$l$$kK!7ck|Wye#lx z%3-5P7f}%LHPzsjV9l?%kt8ThzTF?X_i%XN5>6A zo`q(F#QoZ4{P1#_6$TTBcHG@YZ_xTQqLxztyEyvC_mNFGz7<<)BE98ctpI;wP{I~# z#b2{PlnXJ{`KAyFn1JSWjeA4Q6b>ei;F{PXXYMHs$vEaU;bILctC^l-?n{*ZG$lke zD>3(VAI-wq0JJ#fBqhA_`+u4B)h!!$2VY#(L9eI+@8^?^ban<)C4qZxZ;s$vt67CF8rSL_IQnPd?JA4i z#m+`vSS9+))7&}-qti^rWMx0iux&YD5$69jSps%I+R;zeeoK2H13=IBci2f=o#w3i zzh+4-ng}%s=%Vr8@ro!3-WMN#`Q?w-H?Li>(t#4@5SXdp-lb=w(@y&8UGWB6SNqDR zYguR**PX*^Q!KC1*I}B95Xo1K5}*B~N9g^{U)5e4h6;$C_)rpOXB&Ul#=>|zAE>u^ z1*x~W%_|LhkM}A-{FPFka3o>*i?>yImA6xfLj1>>E?ZWK#Y7}=#$4W^B{<|&oA2z) zt?Mt=@)E^0KV($ww3gW0dv}R8Jv3_Z9T-~%+%0jdg_PRWj*xn~-5HdJH}7#_b{y6M zOaH`oi)`s9ne+AYnVTwsfmO7FNqJ)ruR$J{x33 zSVN~Ol|_n1Sfw@xW|8S+!!WQjj*JwIXelXM$RM_V=;nt{Hz`%oQP>}M&>-%kIQaK3 zFAH`}4+~^s@A^*HV4Qe7#)@_#)~R^go+Wg{)YlxEUJ7c!0&|ko#N+^WNa9SiS^p$H z@*%E3W~CUl>x-NP*Q{>GO0cLRu~R^WC35V+m)pPs5nSNr2H)4{hCg;mBCYJ+1`ICE z-L<+Mo9uqhuh-kg>y1OX*FG7{2$~znrL-S)FaN1%q~;#;^1@3^@>wcC4;Wm1u8)f3 zyaR5QdY+q?xg_OpaIX9!J4|9D8}Qk*us4|ZX!3U<06E(*3AGB{9hBr`##X!hW+EPa zVWt9dXe%X!xHHYIgIEA4WH_TFPE!qc4e4GweLl61?%?wgv+dD<2%)cT@7F zKusGFd5n@Sb3TeSYrs}GG1QT?W4$4+^&S>oamLAtt%%?_V9%Y`5+$@T6?F@fb2gET z7WHPl#fYvwAVW-QHQ>U}<}A4?ow1@SU7e~%+9pq+C!N?EXn>?rF_B1XIIDfWvQMwa zO)0Na{ZIcx44T5=_2s%iZegmZ^P}ExgSG7oaBQ-Gy`p2sG*4_$PEhaH9(`a_C zQp}rKk+&Ri((W8FRj4M2|3{rj-C)O)e5fB2b6w=bok%z8Mn zPQc?w`x5n3e3pqAW>Vby0I`U!xEVCM{)DF+HSo5J{TyM|w>3m(M-_fUz%f|}&8wXNM>kM=uqO7bT^H(V@$vV_OO)-Ewpxx1JrVtjb{Y5IGido$Y_@ z!J9G1)PmFN8O9#kWrafB^*U-#t{lF>jijuvOjIvY6kh%&VfCw$!RDsR${xSM;h?!y zA^ux6SL=8_aCaoRvNK9WrW%oeqs6`hK_56ODdn9j=H)2Tk|$Dk1ObUPBW6bP3G()gc&zctYmjd*k>> z=$^*_z)L=mSfXz)3z`>8vbKd~Km@=v4Vx&NP{MR_W*$qC`rsCJ>f1PctS+h2&a73c=e`5H zJDRVvT|&vQ3o2yYL*$k52P#M?fx0>su(H9F=p((sMQY}XZ*fy3Ios)lgP~J?Sy4KU zI_jVd&h+}ZZ4M*o!$o_}C(zd6$x z3t))tbyGxN`Af$qTc^YSR2d3itvg%DkAt8MY8N)`@toBxEKqV#hNlwbx0%gKFjd6p zj3RH0W8h~^;%vbJ9V`bHi4r_5RTE9?A|L|9&hTXow29A*6_6 zS24-VOB-}RV3gyE8Q;}T+A2-XNqGTlG$ZLQ_3H79Eov=R_!shYDcZL+S>4n-_=a>p z`8~sc8x+*CR|N*WhC)`yRT95;EUCQILK&Tm@&T z#3K(|Arjos`MHH`gr~d3S*@!%7E;Zo=|dL?Q%h58bZe_SN%ZyFPwvlcod6>d%H+|2 z#X5U0Q~y`ub$8Lzj6+@K$9(jV)Z55-ba}54a(n8Hd2xEJ;R*)Lz5}9e*`>6W%sH&? z&U9WfXWiAg#B12Ykc-|OW7Ym%9!KzT<(^QNqucw**G(xzCMnC$Y^zpL;VMx8 z3Ahr4Q4yh>(f+!#s;h1Od)6bxwjX^gN}lRsxlB9VewF?xP6*pYsTJ<( zL)_Fe(vZ|TN4g9+|F;P!cI|SmK|Zb!PUbM(l6hD{BS<{d#qT-^~AZFDc2lS zzSr7D>)KnIQpY`k`^>ekk_s z2p^s$58FIHgar%@qnha5N1kJO3}5*(HS|y0^4z%30DWoXkwW;Qj8o^e{OY<})I+)D$)me4qU!5UvtR9o>v-CPzK=FR za4-Ji@zE@(_xiM>gf-u?`_oBi3@;I&BxF#n*nwn{YTa9w+Ysqh=JLsXl_NNgy+i!1 zW`e7dUME{Zfhu_bx2u0H^7{vO^dK1@U=RhE?+FKb?+epl+wl$TWs8+;1XQM8Ci2cH z+LiLM3HVmqqBnQk)gZ7_s1#6U=m9QRi*@~t*88F4*OKzkjXs(ssNIPAyYbY0fkt zVG3r2NE!~d_}o%8|C^-7AAAY1SH6oe>ASJX=El~PN3GCWS;E#poREtWfPaf?;c1>|iLAmsZU)#dQRD%|l55O%4rETz-~kf<2Uq%?U8K|bYX<(=j8j6DS8x4rA zM)Wjad%-C*O?N{l94H(P0~3NmZ31+tYKyfxkmyN`i#bm zxnYjCGxgNriG+t%VO0p@Uaj1$0JQJ{8iOI!zbJMIIG&2(J~1dtNl<9O-bG1&v$y(( zdzWf^LiP(WMEp|2YcxGun?ff2&GQlCdf!JB%_+&#hitI)9!TEVV%L<;?&;Vf!086m z^P{0Ff|BfSMIe@rxW7v@pU;5%SmqrK~PIQqg5|W6%{1Z?pChfu#qCTzgfL(W~d)lEyAI!_X zu6p@GGl)h=ah%5It@vBTsj+dQ=R00|^Zt3gxAa3yN1sb)l;d;*ZcX}IbGT61T*kVA zCN`G@x*D^SXmBtUY%(rcHpjonOK9o%Myw&3eQ!`)v>($5*brT1VS=+yH2aOdo%k@z zv!qdQHI!bx7-53{pz4%e;nVhgcnLbNGB7z4> zGUro-(9_BiGoQZqm|peYZoXc)!{cHiI&*kV6ekANSfYLEj?$=HVTmyH1-PY&s89ie z6P{V>IJ?Od_R7yyP@hCE-4(bQy?AtVG>NqngnDz{=k#|Z51%5?3^-34miAn0I!-S| z5_-S1B@T}&GOmN*)r&Thdr(}E}pe#HA&bUboJ}xAGKf?|EF3V9|7da_FoepZ;ZeY_&>*o$0^#1)- z+0-TY?uRPcEpP?2nm09@ zMF6UuvH+1S;Xm$ZuSm<3m3aT0^^gDD@b;0ivf9b**lE`Frr?#D?csd$0^6Phv)Y=6 zq0G?r(N721qbK*gd2SPTfo{Wv2L}P?V_2rPcc{&LxS{*pbAPpBYPF8T_yP1Z1|{tPpeYnMQNKW$i!rP)z&yYkdvo|FYj62>M?C6WrUi;Qu`JPyJ>!6<}a5hFvld{hyuqZ@2S*cH;jXUjAFO zeE*+t`tS0{e{$l#8<}7JlN0~jCi-tN`9Hws-yRI`{{`5vV7ic$QDy!Y2X@W=(J=e` z@+oipvTOTaqDo6ejUP>h6NYm}tySM_>hnnb;mn~gP*wI;?cH~O#jN#-oIm+*1K)p} zvwto0egWl__H4(S`-RW02andsdB4*7*9ZOFKk_D@45@(;7xoLDQ;!GxlO$7(f8Q^b zEjPR+0G{oRHt1a3I-^uv?2&cxUi61J-e3f}7$Mk(i(Jvd%g@W;+}NOHYoaJE-x}S#w?!g&qvP*B~pGf>abf zH0>JsFl2vFTJs3`ZfI2$%25+W{ycxArE~-N>d626EdTR**qg?W*AKYAMO2qlul@Vi z{7-=OlRU5}+?^YE_BjaNr+_usT{R=P&-c~xuzryf45d>3Sk3qa_`7L*=UUa(hfn_> DwtSbC diff --git a/docs/src/main/asciidoc/images/remove.txt b/docs/src/main/asciidoc/images/remove.txt deleted file mode 100644 index bbd40769d..000000000 --- a/docs/src/main/asciidoc/images/remove.txt +++ /dev/null @@ -1 +0,0 @@ -please remove once this directory is not empty \ No newline at end of file diff --git a/docs/src/main/asciidoc/images/scf-azure-adapter.svg b/docs/src/main/asciidoc/images/scf-azure-adapter.svg deleted file mode 100644 index 8a064d8f4..000000000 --- a/docs/src/main/asciidoc/images/scf-azure-adapter.svg +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/main/images/ce.png b/docs/src/main/images/ce.png deleted file mode 100644 index e090018e7469bf3567851950b290be321bdc31ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51852 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 NbE;UCS4!4_{{dcyD8T># diff --git a/docs/src/main/ruby/generate_readme.sh b/docs/src/main/ruby/generate_readme.sh deleted file mode 100755 index 6d0ce9dc5..000000000 --- a/docs/src/main/ruby/generate_readme.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env ruby - -base_dir = File.join(File.dirname(__FILE__),'../../..') -src_dir = File.join(base_dir, "/src/main/asciidoc") -require 'asciidoctor' -require 'optparse' - -options = {} -file = "#{src_dir}/README.adoc" - -OptionParser.new do |o| - o.on('-o OUTPUT_FILE', 'Output file (default is stdout)') { |file| options[:to_file] = file unless file=='-' } - o.on('-h', '--help') { puts o; exit } - o.parse! -end - -file = ARGV[0] if ARGV.length>0 - -# Copied from https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/scripts/asciidoc-coalescer.rb -doc = Asciidoctor.load_file file, safe: :unsafe, header_only: true, attributes: options[:attributes] -header_attr_names = (doc.instance_variable_get :@attributes_modified).to_a -header_attr_names.each {|k| doc.attributes[%(#{k}!)] = '' unless doc.attr? k } -attrs = doc.attributes -attrs['allow-uri-read'] = true -puts attrs - -out = "// Do not edit this file (e.g. go instead to src/main/asciidoc)\n\n" -doc = Asciidoctor.load_file file, safe: :unsafe, parse: false, attributes: attrs -out << doc.reader.read - -unless options[:to_file] - puts out -else - File.open(options[:to_file],'w+') do |file| - file.write(out) - end -end diff --git a/pipeline.yml b/pipeline.yml deleted file mode 100644 index fbf8f9e54..000000000 --- a/pipeline.yml +++ /dev/null @@ -1,76 +0,0 @@ -# fly --target cloud login --concourse-url https://ci.spring.io --team-name spring-cloud -# fly --target cloud set-pipeline --config pipeline.yml --pipeline spring-cloud-function --load-vars-from credentials.yml ---- -jobs: - - name: build - plan: - - get: source - trigger: true - - task: maven - config: - platform: linux - image_resource: - type: docker-image - source: - repository: springio/maven-base - inputs: - - name: source - caches: - - path: source/.m2 - run: - dir: source - path: sh - args: - - -c - - | - rm -rf ~/.m2 - ln -s $(pwd)/.m2 ~/.m2 - ./mvnw deploy -s .mvn/settings.xml -Dgpg.passphrase="${passphrase}" - params: - TERM: -dumb - passphrase: {{passphrase}} - sonatype_username: {{sonatype-username}} - sonatype_password: {{sonatype-password}} - spring_username: {{spring-username}} - spring_password: {{spring-password}} - on_failure: *slack-failure - on_success: *slack-success - -slack-failure: &slack-failure - put: slack - params: - channel: spring-cloud-firehose - attachments: - - color: danger - fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " - text: "Build has failed" - title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" - title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME - -slack-success: &slack-success - put: slack - params: - channel: spring-cloud-firehose - attachments: - - color: good - fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " - text: "Build has succeeded" - title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" - title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME - -resources: - - name: source - type: git - source: - uri: https://github.com/spring-cloud/spring-cloud-function.git - - name: slack - type: slack-notification - source: - url: {{slack-url}} - -resource_types: - - name: slack-notification - type: docker-image - source: - repository: nebhale/slack-notification-resource - diff --git a/pom.xml b/pom.xml index bdf655a3a..ef9765fb4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,177 +1,58 @@ - - + + + 4.0.0 - spring-cloud-function-parent - Spring Cloud Function Parent - 4.1.0-SNAPSHOT - pom + org.springframework.cloud + spring-cloud-function-docs-build + 0.0.1-SNAPSHOT - - org.springframework.cloud - spring-cloud-build - 4.1.0-SNAPSHOT - - + Spring Cloud Function Docs Build + Builds Spring Cloud Function Docs. + https://spring.io/projects/spring-cloud-function + + scm:git:https://github.com/spring-cloud/spring-cloud-function.git + + + scm:git:git@github.com:spring-cloud/spring-cloud-function.git + + https://github.com/spring-cloud/spring-cloud-function + + + https://github.com/spring-cloud/spring-cloud-function/issues + - 17 - ${java.version} - ${java.version} - 1.0.27.RELEASE - spring-cloud-function - true - true - - true - + 0.0.3 - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${project.version} - pom - import - - - - + - org.apache.maven.plugins - maven-checkstyle-plugin + io.spring.maven.antora + antora-maven-plugin + ${io.spring.maven.antora-version} + true + + + + + + + + 9d489079e5ec46dbb238909fee5c9c29 + WB1FQYI187 + springcloudfunction + + - - org.apache.maven.plugins - maven-surefire-plugin - - --add-opens java.base/java.util=ALL-UNNAMED - - - - - - - org.codehaus.mojo - flatten-maven-plugin - - - maven-javadoc-plugin - false - - true - com.example,functions,example - - - - - aggregate - - aggregate-jar - - package - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.codehaus.mojo - - - flatten-maven-plugin - - - [1.0.0,) - - - flatten - - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - - - core - - spring-cloud-function-dependencies - spring-cloud-function-core - spring-cloud-function-context - spring-cloud-function-web - - - - all - - true - - - spring-cloud-function-dependencies - spring-cloud-function-core - spring-cloud-function-context - spring-cloud-function-web - spring-cloud-starter-function-web - spring-cloud-starter-function-webflux - spring-cloud-function-samples - spring-cloud-function-deployer - spring-cloud-function-adapters - spring-cloud-function-integration - spring-cloud-function-rsocket - spring-cloud-function-kotlin - docs - - - - spring-snapshots - Spring Snapshots + spring-snapshot https://repo.spring.io/snapshot true @@ -181,49 +62,9 @@ - spring-milestones - Spring Milestones + spring-milestone https://repo.spring.io/milestone - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/release - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/release - - false - - - + diff --git a/spring-cloud-function-adapters/pom.xml b/spring-cloud-function-adapters/pom.xml deleted file mode 100644 index cc9d1fee1..000000000 --- a/spring-cloud-function-adapters/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-adapter-parent - pom - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - spring-cloud-function-adapter-parent - - - spring-cloud-function-adapter-aws - - spring-cloud-function-adapter-azure - spring-cloud-function-adapter-gcp - spring-cloud-function-grpc - spring-cloud-function-grpc-cloudevent-ext - spring-cloud-function-serverless-web - spring-cloud-function-adapter-azure-web - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/README.adoc b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/README.adoc deleted file mode 100644 index 5414034e8..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/README.adoc +++ /dev/null @@ -1,7 +0,0 @@ -//// -DO NOT EDIT THIS FILE. IT WAS GENERATED. -Manual changes to this file will be lost when it is generated again. -Edit the files in the src/main/asciidoc/ directory instead. -//// - -This project provides an adapter layer for a Spring Cloud Function application onto AWS Lambda. You can write an app with a single `@Bean` of type `Function`, `Consumer` or `Supplier` and it will be deployable in AWS if you get the JAR file laid out right. The best way to make it work is to include `spring-cloud-function-context` as a dependency, but not the higher level adapters (e.g. `spring-cloud-function-stream`). 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 deleted file mode 100644 index 0399000f8..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/pom.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-adapter-aws - jar - - spring-cloud-function-adapter-aws - AWS Lambda Adapter for Spring Cloud Function - - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - - - UTF-8 - UTF-8 - 3.9.0 - 1.12.29 - 1.0.3 - 1.0.3 - - - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.boot - spring-boot-starter - - - com.amazonaws - aws-lambda-java-log4j - 1.0.0 - provided - - - com.amazonaws - aws-lambda-java-serialization - 1.0.0 - provided - - - com.amazonaws - aws-lambda-java-core - 1.2.1 - provided - - - com.amazonaws - amazon-kinesis-client - 1.14.4 - provided - - - com.amazonaws - aws-lambda-java-events - ${aws-lambda-events.version} - provided - - - com.amazonaws - aws-java-sdk-kinesis - ${aws-java-sdk.version} - provided - true - - - com.amazonaws - amazon-kinesis-deaggregator - ${aws-kinesis-deaggregator.version} - - - com.amazonaws - aws-lambda-java-events - - - true - provided - - - - - - - - org.springframework - spring-webmvc - - - org.springframework.cloud - spring-cloud-function-web - true - - - org.springframework.boot - spring-boot-starter-test - test - - - com.amazonaws - amazon-kinesis-aggregator - ${aws-kinesis-aggregator.version} - test - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-web - test - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSCompanionAutoConfiguration.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSCompanionAutoConfiguration.java deleted file mode 100644 index de6ac6721..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSCompanionAutoConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021-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 com.fasterxml.jackson.databind.ObjectMapper; - -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.util.CollectionUtils; - - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - * - */ -public class AWSCompanionAutoConfiguration { - - @Bean - public AWSTypesMessageConverter awsTypesMessageConverter(GenericApplicationContext applicationContext) { - JsonMapper jsonMapper = CollectionUtils.isEmpty(applicationContext.getBeansOfType(JsonMapper.class).values()) - ? new JacksonMapper(new ObjectMapper()) - : applicationContext.getBean(JsonMapper.class); - return new AWSTypesMessageConverter(jsonMapper); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSLambdaUtils.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSLambdaUtils.java deleted file mode 100644 index 0923e234b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSLambdaUtils.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2021-2022 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.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import com.amazonaws.services.lambda.runtime.Context; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.http.HttpStatus; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.StreamUtils; - -/** - * - * @author Oleg Zhurakousky - * - */ -public final class AWSLambdaUtils { - - private static Log logger = LogFactory.getLog(AWSLambdaUtils.class); - - static final String AWS_API_GATEWAY = "aws-api-gateway"; - - static final String AWS_EVENT = "aws-event"; - - static final String IS_BASE64_ENCODED = "isBase64Encoded"; - - static final String STATUS_CODE = "statusCode"; - - static final String BODY = "body"; - - static final String HEADERS = "headers"; - - /** - * The name of the headers that stores AWS Context object. - */ - public static final String AWS_CONTEXT = "aws-context"; - - private AWSLambdaUtils() { - - } - - static boolean isSupportedAWSType(Type inputType) { - if (FunctionTypeUtils.isMessage(inputType) || FunctionTypeUtils.isPublisher(inputType)) { - inputType = FunctionTypeUtils.getImmediateGenericType(inputType, 0); - } - return FunctionTypeUtils.getRawType(inputType).getPackage().getName().startsWith("com.amazonaws.services.lambda.runtime.events"); - } - - @SuppressWarnings("rawtypes") - public static Message generateMessage(InputStream payload, Type inputType, boolean isSupplier, JsonMapper jsonMapper, Context context) throws IOException { - if (inputType != null && FunctionTypeUtils.isMessage(inputType)) { - inputType = FunctionTypeUtils.getImmediateGenericType(inputType, 0); - } - if (inputType != null && InputStream.class.isAssignableFrom(FunctionTypeUtils.getRawType(inputType))) { - MessageBuilder msgBuilder = MessageBuilder.withPayload(payload); - if (context != null) { - msgBuilder.setHeader(AWSLambdaUtils.AWS_CONTEXT, context); - } - return msgBuilder.build(); - } - else { - return generateMessage(StreamUtils.copyToByteArray(payload), inputType, isSupplier, jsonMapper, context); - } - } - - public static Message generateMessage(byte[] payload, Type inputType, boolean isSupplier, JsonMapper jsonMapper) { - return generateMessage(payload, inputType, isSupplier, jsonMapper, null); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Message generateMessage(byte[] payload, Type inputType, boolean isSupplier, JsonMapper jsonMapper, Context context) { - if (logger.isInfoEnabled()) { - logger.info("Received: " + new String(payload, StandardCharsets.UTF_8)); - } - - - Object structMessage = jsonMapper.fromJson(payload, Object.class); - boolean isApiGateway = structMessage instanceof Map - && (((Map) structMessage).containsKey("httpMethod") || - (((Map) structMessage).containsKey("routeKey") && ((Map) structMessage).containsKey("version"))); - - Message requestMessage; - MessageBuilder builder = MessageBuilder.withPayload(payload); - if (isApiGateway) { - builder.setHeader(AWSLambdaUtils.AWS_API_GATEWAY, true); - if (JsonMapper.isJsonStringRepresentsCollection(((Map) structMessage).get("body"))) { - builder.setHeader("payload", ((Map) structMessage).get("body")); - } - } - if (!isSupplier && AWSLambdaUtils.isSupportedAWSType(inputType)) { - builder.setHeader(AWSLambdaUtils.AWS_EVENT, true); - } - if (context != null) { - builder.setHeader(AWSLambdaUtils.AWS_CONTEXT, context); - } - // - if (structMessage instanceof Map && ((Map) structMessage).containsKey("headers")) { - builder.copyHeaders((Map) ((Map) structMessage).get("headers")); - } - requestMessage = builder.build(); - return requestMessage; - } - - private static byte[] extractPayload(Message msg, JsonMapper objectMapper) { - if (msg.getPayload() instanceof byte[]) { - return (byte[]) msg.getPayload(); - } - else { - return objectMapper.toJson(msg.getPayload()); - } - } - - private static Object convertFromJsonIfNecessary(Object value, JsonMapper objectMapper) { - if (JsonMapper.isJsonString(value)) { - return objectMapper.fromJson(value, Object.class); - } - return value; - } - - @SuppressWarnings("unchecked") - public static byte[] generateOutputFromObject(Message requestMessage, Object output, JsonMapper objectMapper, Type functionOutputType) { - Message responseMessage = null; - if (output instanceof Publisher) { - List result = new ArrayList<>(); - Message lastMessage = null; - for (Object item : Flux.from((Publisher) output).toIterable()) { - if (logger.isDebugEnabled()) { - logger.debug("Response value: " + item); - } - if (item instanceof Message message) { - result.add(convertFromJsonIfNecessary(message.getPayload(), objectMapper)); - lastMessage = message; - } - else { - result.add(convertFromJsonIfNecessary(item, objectMapper)); - } - } - - byte[] resultPayload; - if (result.size() == 1) { - resultPayload = objectMapper.toJson(result.get(0)); - } - else if (result.size() > 1) { - resultPayload = objectMapper.toJson(result); - } - else { - resultPayload = null; - } - - if (resultPayload != null) { - MessageBuilder messageBuilder = MessageBuilder.withPayload(resultPayload); - if (lastMessage != null) { - messageBuilder.copyHeaders(lastMessage.getHeaders()); - } - responseMessage = messageBuilder.build(); - } - } - else { - responseMessage = (Message) output; - } - return generateOutput(requestMessage, responseMessage, objectMapper, functionOutputType); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static byte[] generateOutput(Message requestMessage, Message responseMessage, - JsonMapper objectMapper, Type functionOutputType) { - - Class outputClass = FunctionTypeUtils.getRawType(functionOutputType); - if (outputClass != null) { - String outputClassName = outputClass.getName(); - if (outputClassName.equals("com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse") || - outputClassName.equals("com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent") || - outputClassName.equals("com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent") || - outputClassName.equals("com.amazonaws.services.lambda.runtime.events.IamPolicyResponse")) { - return extractPayload((Message) responseMessage, objectMapper); - } - } - - byte[] responseBytes = responseMessage == null ? "\"OK\"".getBytes() : extractPayload((Message) responseMessage, objectMapper); - if (requestMessage.getHeaders().containsKey(AWS_API_GATEWAY) && ((boolean) requestMessage.getHeaders().get(AWS_API_GATEWAY))) { - Map response = new HashMap(); - response.put(IS_BASE64_ENCODED, responseMessage != null && responseMessage.getHeaders().containsKey(IS_BASE64_ENCODED) - ? responseMessage.getHeaders().get(IS_BASE64_ENCODED) : false); - - AtomicReference headers = new AtomicReference<>(); - int statusCode = HttpStatus.OK.value(); - if (responseMessage != null) { - headers.set(responseMessage.getHeaders()); - statusCode = headers.get().containsKey(STATUS_CODE) - ? (int) headers.get().get(STATUS_CODE) - : HttpStatus.OK.value(); - } - - response.put(STATUS_CODE, statusCode); - if (isRequestKinesis(requestMessage)) { - HttpStatus httpStatus = HttpStatus.valueOf(statusCode); - response.put("statusDescription", httpStatus.toString()); - } - - String body = responseMessage == null - ? "\"OK\"" : new String(extractPayload((Message) responseMessage, objectMapper), StandardCharsets.UTF_8); - response.put(BODY, body); - if (responseMessage != null) { - Map responseHeaders = new HashMap<>(); - headers.get().keySet().forEach(key -> responseHeaders.put(key, headers.get().get(key).toString())); - response.put(HEADERS, responseHeaders); - } - - try { - responseBytes = objectMapper.toJson(response); - } - catch (Exception e) { - throw new IllegalStateException("Failed to serialize AWS Lambda output", e); - } - } - return responseBytes; - } - - private static boolean isRequestKinesis(Message requestMessage) { - return requestMessage.getHeaders().containsKey("Records"); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSTypesMessageConverter.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSTypesMessageConverter.java deleted file mode 100644 index b94a48181..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/AWSTypesMessageConverter.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2021-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.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.util.Map; - -import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; -import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; - -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.cloud.function.context.config.JsonMessageConverter; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.util.MimeType; - -/** - * Implementation of {@link MessageConverter} which uses Jackson or Gson libraries to do the - * actual conversion via {@link JsonMapper} instance. - * - * @author Oleg Zhurakousky - * - * @since 3.2 - */ -class AWSTypesMessageConverter extends JsonMessageConverter { - - private final JsonMapper jsonMapper; - - AWSTypesMessageConverter(JsonMapper jsonMapper) { - this(jsonMapper, new MimeType("application", "json"), new MimeType(CloudEventMessageUtils.APPLICATION_CLOUDEVENTS.getType(), - CloudEventMessageUtils.APPLICATION_CLOUDEVENTS.getSubtype() + "+json")); - } - - AWSTypesMessageConverter(JsonMapper jsonMapper, MimeType... supportedMimeTypes) { - super(jsonMapper, supportedMimeTypes); - this.jsonMapper = jsonMapper; - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - if (message.getHeaders().containsKey(AWSLambdaUtils.AWS_API_GATEWAY)) { - return ((boolean) message.getHeaders().get(AWSLambdaUtils.AWS_API_GATEWAY)); - } - if (message.getHeaders().containsKey(AWSLambdaUtils.AWS_EVENT)) { - return ((boolean) message.getHeaders().get(AWSLambdaUtils.AWS_EVENT)); - } - //TODO Do we really need the ^^ above? It seems like the line below dows the trick - else if (targetClass.getPackage().getName().startsWith("com.amazonaws.services.lambda.runtime.events")) { - return true; - } - return false; - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, @Nullable Object conversionHint) { - if (message.getPayload().getClass().isAssignableFrom(targetClass)) { - return message.getPayload(); - } - - if (targetClass.getPackage().getName().startsWith("com.amazonaws.services.lambda.runtime.events")) { - PojoSerializer serializer = LambdaEventSerializers.serializerFor(targetClass, Thread.currentThread().getContextClassLoader()); - Object event = serializer.fromJson(new ByteArrayInputStream((byte[]) message.getPayload())); - return event; - } - else { - Map structMessage = this.jsonMapper.fromJson(message.getPayload(), Map.class); - if (targetClass.isAssignableFrom(Map.class)) { - return structMessage; - } - else { - Object body; - if (message.getHeaders().containsKey("payload")) { - body = message.getPayload(); - } - else { - body = structMessage.get("body"); - } - Object convertedResult = this.jsonMapper.fromJson(body, targetClass); - return convertedResult; - } - } - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - if (!supportsMimeType(headers)) { - return false; - } - return true; - } - - - @Override - protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, - @Nullable Object conversionHint) { - if (payload instanceof String && headers.containsKey(AWSLambdaUtils.IS_BASE64_ENCODED) && (boolean) headers.get(AWSLambdaUtils.IS_BASE64_ENCODED)) { - return ((String) payload).getBytes(StandardCharsets.UTF_8); - } - return jsonMapper.toJson(payload); - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoop.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoop.java deleted file mode 100644 index 7e91f7eab..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoop.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2021-2023 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.PrintWriter; -import java.io.StringWriter; -import java.net.SocketException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.web.client.RestTemplate; - -import static org.apache.http.HttpHeaders.USER_AGENT; - -/** - * Event loop and necessary configurations to support AWS Lambda - * Custom Runtime - https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html. - * - * @author Oleg Zhurakousky - * @author Mark Sailes - * @author Rahul Lokurte - * @since 3.1.1 - * - */ -public final class CustomRuntimeEventLoop implements SmartLifecycle { - - private static Log logger = LogFactory.getLog(CustomRuntimeEventLoop.class); - - static final String LAMBDA_VERSION_DATE = "2018-06-01"; - private static final String LAMBDA_ERROR_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/{2}/error"; - private static final String LAMBDA_RUNTIME_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/next"; - private static final String LAMBDA_INVOCATION_URL_TEMPLATE = "http://{0}/{1}/runtime/invocation/{2}/response"; - private static final String USER_AGENT_VALUE = String.format( - "spring-cloud-function/%s-%s", - System.getProperty("java.runtime.version"), - extractVersion()); - - private final ConfigurableApplicationContext applicationContext; - - private volatile boolean running; - - private ExecutorService executor = Executors.newSingleThreadExecutor(); - - public CustomRuntimeEventLoop(ConfigurableApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - public void run() { - this.running = true; - this.executor.execute(() -> { - eventLoop(this.applicationContext); - }); - } - - @Override - public void start() { - this.run(); - } - - @Override - public void stop() { - this.executor.shutdownNow(); - this.running = false; - } - - @Override - public boolean isRunning() { - return this.running; - } - - private void eventLoop(ConfigurableApplicationContext context) { - Environment environment = context.getEnvironment(); - logger.info("Starting spring-cloud-function CustomRuntimeEventLoop"); - if (logger.isDebugEnabled()) { - logger.debug("AWS LAMBDA ENVIRONMENT: " + System.getenv()); - } - - String runtimeApi = environment.getProperty("AWS_LAMBDA_RUNTIME_API"); - String eventUri = MessageFormat.format(LAMBDA_RUNTIME_URL_TEMPLATE, runtimeApi, LAMBDA_VERSION_DATE); - if (logger.isDebugEnabled()) { - logger.debug("Event URI: " + eventUri); - } - - RequestEntity requestEntity = RequestEntity.get(URI.create(eventUri)).header(USER_AGENT, USER_AGENT_VALUE).build(); - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - RestTemplate rest = new RestTemplate(); - JsonMapper mapper = context.getBean(JsonMapper.class); - - logger.info("Entering event loop"); - while (this.isRunning()) { - logger.debug("Attempting to get new event"); - ResponseEntity response = this.pollForData(rest, requestEntity); - - if (logger.isDebugEnabled()) { - logger.debug("New Event received: " + response); - } - - if (response != null && response.hasBody()) { - String requestId = response.getHeaders().getFirst("Lambda-Runtime-Aws-Request-Id"); - try { - FunctionInvocationWrapper function = locateFunction(environment, functionCatalog, response.getHeaders()); - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBody().getBytes(StandardCharsets.UTF_8)); - Message requestMessage = AWSLambdaUtils.generateMessage(is, function.getInputType(), function.isSupplier(), mapper, null); - - Object functionResponse = function.apply(requestMessage); - byte[] responseBytes = AWSLambdaUtils.generateOutputFromObject(requestMessage, functionResponse, mapper, function.getOutputType()); - - String invocationUrl = MessageFormat - .format(LAMBDA_INVOCATION_URL_TEMPLATE, runtimeApi, LAMBDA_VERSION_DATE, requestId); - - ResponseEntity result = rest.exchange(RequestEntity.post(URI.create(invocationUrl)) - .header(USER_AGENT, USER_AGENT_VALUE) - .body(responseBytes), Object.class); - - if (logger.isInfoEnabled()) { - logger.info("Result POST status: " + result); - } - } - catch (Exception e) { - this.propagateAwsError(requestId, e, mapper, runtimeApi, rest); - } - } - } - } - - private void propagateAwsError(String requestId, Exception e, JsonMapper mapper, String runtimeApi, RestTemplate rest) { - String errorMessage = e.getMessage(); - String errorType = e.getClass().getSimpleName(); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - String stackTrace = sw.toString(); - Map em = new HashMap<>(); - em.put("errorMessage", errorMessage); - em.put("errorType", errorType); - em.put("stackTrace", stackTrace); - byte[] outputBody = mapper.toJson(em); - try { - String errorUrl = MessageFormat.format(LAMBDA_ERROR_URL_TEMPLATE, runtimeApi, LAMBDA_VERSION_DATE, requestId); - ResponseEntity result = rest.exchange(RequestEntity.post(URI.create(errorUrl)) - .header(USER_AGENT, USER_AGENT_VALUE) - .body(outputBody), Object.class); - if (logger.isInfoEnabled()) { - logger.info("Result ERROR status: " + result.getStatusCode()); - } - } - catch (Exception e2) { - throw new IllegalArgumentException("Failed to report error", e2); - } - } - - private ResponseEntity pollForData(RestTemplate rest, RequestEntity requestEntity) { - try { - return rest.exchange(requestEntity, String.class); - } - catch (Exception e) { - if (e instanceof SocketException) { - this.stop(); - // ignore - } - } - return null; - } - - private FunctionInvocationWrapper locateFunction(Environment environment, FunctionCatalog functionCatalog, - HttpHeaders httpHeaders) { - MediaType contentType = httpHeaders.getContentType(); - String handlerName = environment.getProperty("DEFAULT_HANDLER"); - if (logger.isDebugEnabled()) { - logger.debug("Value of DEFAULT_HANDLER env: " + handlerName); - } - FunctionInvocationWrapper function = functionCatalog.lookup(handlerName, contentType.toString()); - if (function == null) { - logger.debug("Could not locate function under DEFAULT_HANDLER"); - handlerName = environment.getProperty("_HANDLER"); - if (logger.isDebugEnabled()) { - logger.debug("Value of _HANDLER env: " + handlerName); - } - function = functionCatalog.lookup(handlerName, contentType.toString()); - } - - if (function == null) { - logger.debug("Could not locate function under _HANDLER"); - function = functionCatalog.lookup((String) null, contentType.toString()); - } - - if (function == null) { - logger.info("Could not determine default function"); - handlerName = environment.getProperty("spring.cloud.function.definition"); - if (logger.isDebugEnabled()) { - logger.debug("Value of 'spring.cloud.function.definition' env: " + handlerName); - } - function = functionCatalog.lookup(handlerName, contentType.toString()); - } - - if (function == null) { - logger.info("Could not determine DEFAULT_HANDLER, _HANDLER or 'spring.cloud.function.definition'"); - handlerName = httpHeaders.getFirst("spring.cloud.function.definition"); - if (logger.isDebugEnabled()) { - logger.debug("Value of 'spring.cloud.function.definition' header: " + handlerName); - } - function = functionCatalog.lookup(handlerName, contentType.toString()); - } - - if (function == null) { - function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME, "application/json"); - if (function != null && logger.isInfoEnabled()) { - logger.info("Will default to RoutingFunction, since multiple functions available in FunctionCatalog." - + "Expecting 'spring.cloud.function.definition' or 'spring.cloud.function.routing-expression' as Message headers. " - + "If invocation is over API Gateway, Message headers can be provided as HTTP headers."); - } - } - - Assert.notNull(function, "Failed to locate function. Tried locating default function, " - + "function by 'DEFAULT_HANDLER', '_HANDLER' env variable as well as'spring.cloud.function.definition'. " - + "Functions available in catalog are: " + functionCatalog.getNames(null)); - if (function != null && logger.isInfoEnabled()) { - logger.info("Located function " + function.getFunctionDefinition()); - } - return function; - } - - private static String extractVersion() { - try { - String path = CustomRuntimeEventLoop.class.getProtectionDomain().getCodeSource().getLocation().toString(); - int endIndex = path.lastIndexOf('.'); - if (endIndex < 0) { - return "UNKNOWN-VERSION"; - } - int startIndex = path.lastIndexOf("/") + 1; - return path.substring(startIndex, endIndex).replace("spring-cloud-function-adapter-aws-", ""); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to detect version", e); - } - return "UNKNOWN-VERSION"; - } - - } -} 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 deleted file mode 100644 index 50294cb28..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeInitializer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2018-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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.SmartLifecycle; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.util.StringUtils; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class CustomRuntimeInitializer implements ApplicationContextInitializer { - - private static Log logger = LogFactory.getLog(CustomRuntimeInitializer.class); - - @Override - public void initialize(GenericApplicationContext context) { - Environment environment = context.getEnvironment(); - if (logger.isDebugEnabled()) { - logger.debug("AWS Environment: " + System.getenv()); - } - - if (!this.isWebExportEnabled(context) && isCustomRuntime(environment)) { - if (context.getBeanFactory().getBeanNamesForType(CustomRuntimeEventLoop.class, false, false).length == 0) { - context.registerBean(StringUtils.uncapitalize(CustomRuntimeEventLoop.class.getSimpleName()), - SmartLifecycle.class, () -> new CustomRuntimeEventLoop(context)); - } - } - } - - private boolean isCustomRuntime(Environment environment) { - String handler = environment.getProperty("_HANDLER"); - if (StringUtils.hasText(handler)) { - handler = handler.split(":")[0]; - logger.info("AWS Handler: " + handler); - try { - Class clazz = Thread.currentThread().getContextClassLoader().loadClass(handler); - if (FunctionInvoker.class.isAssignableFrom(clazz)) { - return false; - } - } - catch (Exception e) { - logger.debug("Will execute Lambda in Custom Runtime"); - return true; - } - } - return false; - } - - - private boolean isWebExportEnabled(GenericApplicationContext context) { - Boolean enabled = context.getEnvironment() - .getProperty("spring.cloud.function.web.export.enabled", Boolean.class); - return enabled != null && enabled; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java deleted file mode 100644 index 107ca418e..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/FunctionInvoker.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2019-2022 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.Set; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.MapperFeature; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringApplication; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionalSpringApplication; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.utils.FunctionClassUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.StreamUtils; -import org.springframework.util.StringUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.1 - * - * see - * https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format - */ -public class FunctionInvoker implements RequestStreamHandler { - - private static Log logger = LogFactory.getLog(FunctionInvoker.class); - - private JsonMapper jsonMapper; - - private FunctionInvocationWrapper function; - - private volatile String functionDefinition; - - private boolean started; - - public FunctionInvoker(String functionDefinition) { - this.functionDefinition = functionDefinition; - String lateInitialization = System.getenv("FUNCTION_INVOKER_LATE_INITIALIZATION"); - if (!StringUtils.hasText(lateInitialization) || !Boolean.parseBoolean(lateInitialization)) { - this.start(); - } - else { - logger.info("Spring Application Context will be initialized on first request"); - } - } - - public FunctionInvoker() { - this(null); - } - - @SuppressWarnings({ "rawtypes" }) - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - if (!this.started) { - this.start(); - } - Message requestMessage = AWSLambdaUtils - .generateMessage(input, this.function.getInputType(), this.function.isSupplier(), jsonMapper, context); - - Object response = this.function.apply(requestMessage); - byte[] responseBytes = AWSLambdaUtils.generateOutputFromObject(requestMessage, response, this.jsonMapper, function.getOutputType()); - StreamUtils.copy(responseBytes, output); - // any exception should propagate - } - - private void start() { - Class startClass = FunctionClassUtils.getStartClass(); - String[] properties = new String[] {"--spring.cloud.function.web.export.enabled=false", "--spring.main.web-application-type=none"}; - ConfigurableApplicationContext context = ApplicationContextInitializer.class.isAssignableFrom(startClass) - ? FunctionalSpringApplication.run(new Class[] {startClass, AWSCompanionAutoConfiguration.class}, properties) - : SpringApplication.run(new Class[] {startClass, AWSCompanionAutoConfiguration.class}, properties); - - Environment environment = context.getEnvironment(); - if (!StringUtils.hasText(this.functionDefinition)) { - this.functionDefinition = environment.getProperty(FunctionProperties.FUNCTION_DEFINITION); - } - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - this.jsonMapper = context.getBean(JsonMapper.class); - if (this.jsonMapper instanceof JacksonMapper) { - ((JacksonMapper) this.jsonMapper).configureObjectMapper(objectMapper -> { - if (!objectMapper.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)) { - objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); - } - }); - } - - if (logger.isInfoEnabled()) { - logger.info("Locating function: '" + this.functionDefinition + "'"); - } - - this.function = functionCatalog.lookup(this.functionDefinition, "application/json"); - - if (this.function == null) { - if (logger.isInfoEnabled()) { - if (!StringUtils.hasText(this.functionDefinition)) { - logger.info("Failed to determine default function. Please use 'spring.cloud.function.definition' property " - + "or pass function definition as a constructir argument to this FunctionInvoker"); - } - Set names = functionCatalog.getNames(null); - if (names.size() == 1) { - logger.info("Will default to RoutingFunction, since it is the only function available in FunctionCatalog." - + "Expecting 'spring.cloud.function.definition' or 'spring.cloud.function.routing-expression' as Message headers. " - + "If invocation is over API Gateway, Message headers can be provided as HTTP headers."); - } - else { - logger.info("More then one function is available in FunctionCatalog. " + names - + " Will default to RoutingFunction, " - + "Expecting 'spring.cloud.function.definition' or 'spring.cloud.function.routing-expression' as Message headers. " - + "If invocation is over API Gateway, Message headers can be provided as HTTP headers."); - } - } - this.function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME, "application/json"); - } - - if (this.function.isOutputTypePublisher()) { - this.function.setSkipOutputConversion(true); - } - Assert.notNull(this.function, "Failed to lookup function " + this.functionDefinition); - - this.functionDefinition = this.function.getFunctionDefinition(); - if (logger.isInfoEnabled()) { - logger.info("Located function: '" + this.functionDefinition + "'"); - } - this.started = true; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/LambdaDestinationResolver.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/LambdaDestinationResolver.java deleted file mode 100644 index 61b1f8bf9..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/aws/LambdaDestinationResolver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2018-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.Supplier; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.web.source.DestinationResolver; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; - -/** - * Implementation of {@link DestinationResolver}for AWS Lambda which resolves destination - * from `lambda-runtime-aws-request-id` message header. - * - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -public class LambdaDestinationResolver implements DestinationResolver { - - private static Log logger = LogFactory.getLog(LambdaDestinationResolver.class); - - @Override - public String destination(Supplier supplier, String name, Object value) { - if (logger.isDebugEnabled()) { - logger.debug("Lambda invoming value: " + value); - } - String destination = "unknown"; - if (value instanceof Message) { - Message message = (Message) value; - MessageHeaders headers = message.getHeaders(); - if (headers.containsKey("lambda-runtime-aws-request-id")) { - destination = (String) headers.get("lambda-runtime-aws-request-id"); - } - } - if (logger.isDebugEnabled()) { - logger.debug("Lambda destination resolved to: " + destination); - } - return destination; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/test/aws/AWSCustomRuntime.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/test/aws/AWSCustomRuntime.java deleted file mode 100644 index 4b396511a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/java/org/springframework/cloud/function/adapter/test/aws/AWSCustomRuntime.java +++ /dev/null @@ -1,98 +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.test.aws; - -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.core.env.MapPropertySource; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeTypeUtils; - -/** - * AWS Custom Runtime emulator to be used for testing. - * - * @author Oleg Zhurakousky - * @since 3.2 - */ -@EnableAutoConfiguration -public class AWSCustomRuntime { - - BlockingQueue inputQueue = new ArrayBlockingQueue<>(3); - - BlockingQueue> outputQueue = new ArrayBlockingQueue<>(3); - - public AWSCustomRuntime(ConfigurableApplicationContext context) { - context.getEnvironment().getPropertySources().addFirst( - new MapPropertySource("AWSCustomRuntime", - Map.of("AWS_LAMBDA_RUNTIME_API", "localhost:${local.server.port}"))); - } - - @Bean("2018-06-01/runtime/invocation/consume/response") - Consumer> consume() { - return v -> outputQueue.offer(v); - } - - @SuppressWarnings("unchecked") - @Bean("2018-06-01/runtime/invocation/next") - Supplier> supply() { - - return () -> { - try { - Object value = inputQueue.poll(1L, TimeUnit.SECONDS); - if (value == null) { - return MessageBuilder.withPayload("").build(); - } - if (!(value instanceof Message)) { - return MessageBuilder.withPayload((String) value) - .setHeader("Lambda-Runtime-Aws-Request-Id", "consume") - .setHeader("Content-Type", - MimeTypeUtils.APPLICATION_JSON) - .build(); - } - else { - return (Message) value; - } - - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException(e); - } - }; - } - - public Message exchange(Object input) { - inputQueue.offer(input); - try { - return outputQueue.poll(5000, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return null; - } - } - -} 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 deleted file mode 100644 index f28be4c77..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.context.ApplicationContextInitializer=\ -org.springframework.cloud.function.adapter.aws.CustomRuntimeInitializer diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 939bd963c..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.adapter.aws.AWSCompanionAutoConfiguration diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoopTest.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoopTest.java deleted file mode 100644 index 868c2ba01..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/CustomRuntimeEventLoopTest.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2021-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.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.adapter.test.aws.AWSCustomRuntime; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.stereotype.Component; -import org.springframework.test.annotation.DirtiesContext; - -import static org.assertj.core.api.Assertions.assertThat; -/** - * - * @author Oleg Zhurakousky - */ -public class CustomRuntimeEventLoopTest { - - private String API_EVENT = "{\n" - + " \"version\": \"1.0\",\n" - + " \"resource\": \"$default\",\n" - + " \"path\": \"/question\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"headers\": {\n" - + " \"Content-Length\": \"40\",\n" - + " \"Content-Type\": \"application/json\",\n" - + " \"Host\": \"emcdxu5ijj.execute-api.us-east-2.amazonaws.com\",\n" - + " \"User-Agent\": \"curl/7.88.1\",\n" - + " \"X-Amzn-Trace-Id\": \"Root=1-64ad9787-4c89d5af7607eb9e522e01d5\",\n" - + " \"X-Forwarded-For\": \"109.210.252.44\",\n" - + " \"X-Forwarded-Port\": \"443\",\n" - + " \"X-Forwarded-Proto\": \"https\",\n" - + " \"accept\": \"*/*\"\n" - + " },\n" - + " \"multiValueHeaders\": {\n" - + " \"Content-Length\": [\n" - + " \"40\"\n" - + " ],\n" - + " \"Content-Type\": [\n" - + " \"application/json\"\n" - + " ],\n" - + " \"Host\": [\n" - + " \"emcdxu5ijj.execute-api.us-east-2.amazonaws.com\"\n" - + " ],\n" - + " \"User-Agent\": [\n" - + " \"curl/7.88.1\"\n" - + " ],\n" - + " \"X-Amzn-Trace-Id\": [\n" - + " \"Root=1-64ad9787-4c89d5af7607eb9e522e01d5\"\n" - + " ],\n" - + " \"X-Forwarded-For\": [\n" - + " \"109.210.252.44\"\n" - + " ],\n" - + " \"X-Forwarded-Port\": [\n" - + " \"443\"\n" - + " ],\n" - + " \"X-Forwarded-Proto\": [\n" - + " \"https\"\n" - + " ],\n" - + " \"accept\": [\n" - + " \"*/*\"\n" - + " ]\n" - + " },\n" - + " \"queryStringParameters\": null,\n" - + " \"multiValueQueryStringParameters\": null,\n" - + " \"requestContext\": {\n" - + " \"accountId\": \"313369169943\",\n" - + " \"apiId\": \"emcdxu5ijj\",\n" - + " \"domainName\": \"emcdxu5ijj.execute-api.us-east-2.amazonaws.com\",\n" - + " \"domainPrefix\": \"emcdxu5ijj\",\n" - + " \"extendedRequestId\": \"H6SdPgXtiYcEP1w=\",\n" - + " \"httpMethod\": \"POST\",\n" - + " \"identity\": {\n" - + " \"accessKey\": null,\n" - + " \"accountId\": null,\n" - + " \"caller\": null,\n" - + " \"cognitoAmr\": null,\n" - + " \"cognitoAuthenticationProvider\": null,\n" - + " \"cognitoAuthenticationType\": null,\n" - + " \"cognitoIdentityId\": null,\n" - + " \"cognitoIdentityPoolId\": null,\n" - + " \"principalOrgId\": null,\n" - + " \"sourceIp\": \"109.210.252.44\",\n" - + " \"user\": null,\n" - + " \"userAgent\": \"curl/7.88.1\",\n" - + " \"userArn\": null\n" - + " },\n" - + " \"path\": \"/question\",\n" - + " \"protocol\": \"HTTP/1.1\",\n" - + " \"requestId\": \"H6SdPgXtiYcEP1w=\",\n" - + " \"requestTime\": \"11/Jul/2023:17:55:19 +0000\",\n" - + " \"requestTimeEpoch\": 1689098119662,\n" - + " \"resourceId\": \"$default\",\n" - + " \"resourcePath\": \"$default\",\n" - + " \"stage\": \"$default\"\n" - + " },\n" - + " \"pathParameters\": null,\n" - + " \"stageVariables\": null,\n" - + " \"body\": \"[{\\\"latitude\\\": 41.34, \\\"longitude\\\": 2.78},{\\\"latitude\\\": 43.24, \\\"longitude\\\": 3.78}]\",\n" - + " \"isBase64Encoded\": false\n" - + "}"; - - @Test - public void testDefaultFunctionLookup() throws Exception { - testDefaultFunctionLookup("uppercase", SingleFunctionConfiguration.class); - } - - @Test - public void testDefaultFunctionLookupReactive() throws Exception { - testDefaultFunctionLookup("uppercase", SingleFunctionConfigurationReactive.class); - } - - private void testDefaultFunctionLookup(String handler, Class context) throws Exception { - try (ConfigurableApplicationContext userContext = - new SpringApplicationBuilder(context, AWSCustomRuntime.class) - .web(WebApplicationType.SERVLET) - .properties("_HANDLER=" + handler, "server.port=0") - .run()) { - - AWSCustomRuntime aws = userContext.getBean(AWSCustomRuntime.class); - Message replyMessage = aws.exchange("\"ricky\""); - assertThat(replyMessage.getHeaders()).containsKey("user-agent"); - assertThat(((String) replyMessage.getHeaders().get("user-agent"))).startsWith("spring-cloud-function"); - assertThat(aws.exchange("\"ricky\"").getPayload()).isEqualTo("\"RICKY\""); - assertThat(aws.exchange("\"julien\"").getPayload()).isEqualTo("\"JULIEN\""); - assertThat(aws.exchange("\"bubbles\"").getPayload()).isEqualTo("\"BUBBLES\""); - } - } - - @Test - public void testDefaultFunctionAsComponentLookup() throws Exception { - try (ConfigurableApplicationContext userContext = - new SpringApplicationBuilder(PersonFunction.class, AWSCustomRuntime.class) - .web(WebApplicationType.SERVLET) - .properties("_HANDLER=personFunction", "server.port=0") - .run()) { - - AWSCustomRuntime aws = userContext.getBean(AWSCustomRuntime.class); - - assertThat(aws.exchange("\"ricky\"").getPayload()).isEqualTo("{\"name\":\"RICKY\"}"); - assertThat(aws.exchange("\"julien\"").getPayload()).isEqualTo("{\"name\":\"JULIEN\"}"); - assertThat(aws.exchange("\"bubbles\"").getPayload()).isEqualTo("{\"name\":\"BUBBLES\"}"); - } - } - - @Test - public void test_HANDLERlookupAndPojoFunction() throws Exception { - try (ConfigurableApplicationContext userContext = - new SpringApplicationBuilder(MultipleFunctionConfiguration.class, AWSCustomRuntime.class) - .web(WebApplicationType.SERVLET) - .properties("_HANDLER=uppercasePerson", "server.port=0") - .run()) { - - AWSCustomRuntime aws = userContext.getBean(AWSCustomRuntime.class); - - assertThat(aws.exchange("\"ricky\"").getPayload()).isEqualTo("{\"name\":\"RICKY\"}"); - assertThat(aws.exchange("\"julien\"").getPayload()).isEqualTo("{\"name\":\"JULIEN\"}"); - assertThat(aws.exchange("\"bubbles\"").getPayload()).isEqualTo("{\"name\":\"BUBBLES\"}"); - } - } - - @Test - public void test_HANDLERWithApiGatewayRequestAndFlux() throws Exception { - try (ConfigurableApplicationContext userContext = - new SpringApplicationBuilder(MultipleFunctionConfiguration.class, AWSCustomRuntime.class) - .web(WebApplicationType.SERVLET) - .properties("_HANDLER=echoFlux", "server.port=0") - .run()) { - - AWSCustomRuntime aws = userContext.getBean(AWSCustomRuntime.class); - String response = aws.exchange(API_EVENT).getPayload(); - assertThat(response).contains("{\\\"latitude\\\":2.78,\\\"longitude\\\":41.34}"); - assertThat(response).contains("{\\\"latitude\\\":3.78,\\\"longitude\\\":43.24}"); - } - } - - @Test - @DirtiesContext - public void test_definitionLookupAndComposition() throws Exception { - try (ConfigurableApplicationContext userContext = - new SpringApplicationBuilder(MultipleFunctionConfiguration.class, AWSCustomRuntime.class) - .web(WebApplicationType.SERVLET) - .properties("_HANDLER=toPersonJson|uppercasePerson", "server.port=0") - .run()) { - - AWSCustomRuntime aws = userContext.getBean(AWSCustomRuntime.class); - - assertThat(aws.exchange("\"ricky\"").getPayload()).isEqualTo("{\"name\":\"RICKY\"}"); - assertThat(aws.exchange("\"julien\"").getPayload()).isEqualTo("{\"name\":\"JULIEN\"}"); - assertThat(aws.exchange("\"bubbles\"").getPayload()).isEqualTo("{\"name\":\"BUBBLES\"}"); - } - - } - - @EnableAutoConfiguration - protected static class SingleFunctionConfiguration { - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - } - - @EnableAutoConfiguration - protected static class SingleFunctionConfigurationReactive { - @Bean - public Function, Flux> uppercase() { - return v -> v.map(String::toUpperCase); - } - } - - @EnableAutoConfiguration - @Configuration(proxyBeanMethods = false) - protected static class MultipleFunctionConfiguration { - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function toPersonJson() { - return v -> "{\"name\":\"" + v + "\"}"; - } - - @Bean - public Function uppercasePerson() { - return p -> new Person(p.getName().toUpperCase()); - } - - @Bean - public Function, Flux> echoFlux() { - return flux -> flux.map(g -> { - return new GeoLocation(g.longitude(), g.latitude()); - }); - } - } - - @EnableAutoConfiguration - @Component("personFunction") // need in test explicitly since it is inner class and name wil be `customRuntimeEventLoopTest.PersonFunction` - public static class PersonFunction implements Function { - - public PersonFunction() { - System.out.println(); - } - - @Override - public Person apply(Person input) { - return new Person(input.getName().toUpperCase()); - } - } - - public static class Person { - private String name; - - public Person() { - - } - - public Person(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - - public record GeoLocation(Float latitude, Float longitude) { - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java deleted file mode 100644 index 83959248e..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/FunctionInvokerTests.java +++ /dev/null @@ -1,1830 +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.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Collections; -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.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayCustomAuthorizerEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; -import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; -import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent; -import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.amazonaws.services.lambda.runtime.events.S3Event; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; -import org.springframework.util.StreamUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class FunctionInvokerTests { - - ObjectMapper mapper = new ObjectMapper(); - - String jsonCollection = "[\"Ricky\",\"Julien\",\"Bubbles\"]"; - - String jsonPojoCollection = "[{\"name\":\"Ricky\"},{\"name\":\"Julien\"},{\"name\":\"Julien\"}]"; - - String dynamoDbEvent = "{\n" - + " \"Records\": [\n" - + " {\n" - + " \"eventID\": \"f07f8ca4b0b26cb9c4e5e77e69f274ee\",\n" - + " \"eventName\": \"INSERT\",\n" - + " \"eventVersion\": \"1.1\",\n" - + " \"eventSource\": \"aws:dynamodb\",\n" - + " \"awsRegion\": \"us-east-1\",\n" - + " \"userIdentity\":{\n" - + " \"type\":\"Service\",\n" - + " \"principalId\":\"dynamodb.amazonaws.com\"\n" - + " },\n" - + " \"dynamodb\": {\n" - + " \"ApproximateCreationDateTime\": 1.684934517E9,\n" - + " \"Keys\": {\n" - + " \"val\": {\n" - + " \"S\": \"data\"\n" - + " },\n" - + " \"key\": {\n" - + " \"S\": \"binary\"\n" - + " }\n" - + " },\n" - + " \"NewImage\": {\n" - + " \"val\": {\n" - + " \"S\": \"data\"\n" - + " },\n" - + " \"asdf1\": {\n" - + " \"B\": \"AAEqQQ==\"\n" - + " },\n" - + " \"asdf2\": {\n" - + " \"BS\": [\n" - + " \"AAEqQQ==\",\n" - + " \"QSoBAA==\"\n" - + " ]\n" - + " },\n" - + " \"key\": {\n" - + " \"S\": \"binary\"\n" - + " }\n" - + " },\n" - + " \"SequenceNumber\": \"1405400000000002063282832\",\n" - + " \"SizeBytes\": 54,\n" - + " \"StreamViewType\": \"NEW_AND_OLD_IMAGES\"\n" - + " },\n" - + " \"eventSourceARN\": \"arn:aws:dynamodb:us-east-1:123456789012:table/Example-Table/stream/2016-12-01T00:00:00.000\"\n" - + " },\n" - + " {\n" - + " \"eventID\": \"f07f8ca4b0b26cb9c4e5e77e42f274ee\",\n" - + " \"eventName\": \"INSERT\",\n" - + " \"eventVersion\": \"1.1\",\n" - + " \"eventSource\": \"aws:dynamodb\",\n" - + " \"awsRegion\": \"us-east-1\",\n" - + " \"dynamodb\": {\n" - + " \"ApproximateCreationDateTime\": 1480642020,\n" - + " \"Keys\": {\n" - + " \"val\": {\n" - + " \"S\": \"data\"\n" - + " },\n" - + " \"key\": {\n" - + " \"S\": \"binary\"\n" - + " }\n" - + " },\n" - + " \"NewImage\": {\n" - + " \"val\": {\n" - + " \"S\": \"data\"\n" - + " },\n" - + " \"asdf1\": {\n" - + " \"B\": \"AAEqQQ==\"\n" - + " },\n" - + " \"b2\": {\n" - + " \"B\": \"test\"\n" - + " },\n" - + " \"asdf2\": {\n" - + " \"BS\": [\n" - + " \"AAEqQQ==\",\n" - + " \"QSoBAA==\",\n" - + " \"AAEqQQ==\"\n" - + " ]\n" - + " },\n" - + " \"key\": {\n" - + " \"S\": \"binary\"\n" - + " },\n" - + " \"Binary\": {\n" - + " \"B\": \"AAEqQQ==\"\n" - + " },\n" - + " \"Boolean\": {\n" - + " \"BOOL\": true\n" - + " },\n" - + " \"BinarySet\": {\n" - + " \"BS\": [\n" - + " \"AAEqQQ==\",\n" - + " \"AAEqQQ==\"\n" - + " ]\n" - + " },\n" - + " \"List\": {\n" - + " \"L\": [\n" - + " {\n" - + " \"S\": \"Cookies\"\n" - + " },\n" - + " {\n" - + " \"S\": \"Coffee\"\n" - + " },\n" - + " {\n" - + " \"N\": \"3.14159\"\n" - + " }\n" - + " ]\n" - + " },\n" - + " \"Map\": {\n" - + " \"M\": {\n" - + " \"Name\": {\n" - + " \"S\": \"Joe\"\n" - + " },\n" - + " \"Age\": {\n" - + " \"N\": \"35\"\n" - + " }\n" - + " }\n" - + " },\n" - + " \"FloatNumber\": {\n" - + " \"N\": \"123.45\"\n" - + " },\n" - + " \"IntegerNumber\": {\n" - + " \"N\": \"123\"\n" - + " },\n" - + " \"NumberSet\": {\n" - + " \"NS\": [\n" - + " \"1234\",\n" - + " \"567.8\"\n" - + " ]\n" - + " },\n" - + " \"Null\": {\n" - + " \"NULL\": true\n" - + " },\n" - + " \"String\": {\n" - + " \"S\": \"Hello\"\n" - + " },\n" - + " \"StringSet\": {\n" - + " \"SS\": [\n" - + " \"Giraffe\",\n" - + " \"Zebra\"\n" - + " ]\n" - + " },\n" - + " \"EmptyStringSet\": {\n" - + " \"SS\": []\n" - + " }\n" - + " },\n" - + " \"SequenceNumber\": \"1405400000000002063282832\",\n" - + " \"SizeBytes\": 54,\n" - + " \"StreamViewType\": \"NEW_AND_OLD_IMAGES\"\n" - + " },\n" - + " \"eventSourceARN\": \"arn:aws:dynamodb:us-east-1:123456789012:table/Example-Table/stream/2016-12-01T00:00:00.000\"\n" - + " }\n" - + " ]\n" - + "}"; - - String sampleLBEvent = "{\n" - + " \"requestContext\": {\n" - + " \"elb\": {\n" - + " \"targetGroupArn\": \"arn:aws:elasticloadbalancing:us-east-1:XXXXXXXXXXX:targetgroup/sample/6d0ecf831eec9f09\"\n" - + " }\n" - + " },\n" - + " \"httpMethod\": \"GET\",\n" - + " \"path\": \"/\",\n" - + " \"queryStringParameters\": {},\n" - + " \"headers\": {\n" - + " \"accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n" - + " \"accept-encoding\": \"gzip\",\n" - + " \"accept-language\": \"en-US,en;q=0.5\",\n" - + " \"connection\": \"keep-alive\",\n" - + " \"cookie\": \"name=value\",\n" - + " \"host\": \"lambda-YYYYYYYY.elb.amazonaws.com\",\n" - + " \"upgrade-insecure-requests\": \"1\",\n" - + " \"user-agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:60.0) Gecko/20100101 Firefox/60.0\",\n" - + " \"x-amzn-trace-id\": \"Root=1-5bdb40ca-556d8b0c50dc66f0511bf520\",\n" - + " \"x-forwarded-for\": \"192.0.2.1\",\n" - + " \"x-forwarded-port\": \"80\",\n" - + " \"x-forwarded-proto\": \"http\"\n" - + " },\n" - + " \"body\": \"Hello from ELB\",\n" - + " \"isBase64Encoded\": false\n" - + "}"; - - String sampleSQSEvent = "{\n" + - " \"Records\": [\n" + - " {\n" + - " \"messageId\": \"19dd0b57-b21e-4ac1-bd88-01bbb068cb78\",\n" + - " \"receiptHandle\": \"MessageReceiptHandle\",\n" + - " \"body\": \"Hello from SQS!\",\n" + - " \"attributes\": {\n" + - " \"ApproximateReceiveCount\": \"1\",\n" + - " \"SentTimestamp\": \"1523232000000\",\n" + - " \"SenderId\": \"123456789012\",\n" + - " \"ApproximateFirstReceiveTimestamp\": \"1523232000001\"\n" + - " },\n" + - " \"messageAttributes\": {},\n" + - " \"md5OfBody\": \"7b270e59b47ff90a553787216d55d91d\",\n" + - " \"eventSource\": \"aws:sqs\",\n" + - " \"eventSourceARN\": \"arn:aws:sqs:eu-central-1:123456789012:MyQueue\",\n" + - " \"awsRegion\": \"eu-central-1\"\n" + - " }\n" + - " ]\n" + - "}"; - - String sampleSNSEvent = "{\n" + - " \"Records\": [\n" + - " {\n" + - " \"EventVersion\": \"1.0\",\n" + - " \"EventSubscriptionArn\": \"arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + - " \"EventSource\": \"aws:sns\",\n" + - " \"Sns\": {\n" + - " \"SignatureVersion\": \"1\",\n" + - " \"Timestamp\": \"2019-01-02T12:45:07.000Z\",\n" + - " \"Signature\": \"tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==\",\n" + - " \"SigningCertUrl\": \"https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem\",\n" + - " \"MessageId\": \"95df01b4-ee98-5cb9-9903-4c221d41eb5e\",\n" + - " \"Message\": \"Hello from SNS!\",\n" + - " \"MessageAttributes\": {\n" + - " \"Test\": {\n" + - " \"Type\": \"String\",\n" + - " \"Value\": \"TestString\"\n" + - " },\n" + - " \"TestBinary\": {\n" + - " \"Type\": \"Binary\",\n" + - " \"Value\": \"TestBinary\"\n" + - " }\n" + - " },\n" + - " \"Type\": \"Notification\",\n" + - " \"UnsubscribeUrl\": \"https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + - " \"TopicArn\":\"arn:aws:sns:us-east-2:123456789012:sns-lambda\",\n" + - " \"Subject\": \"TestInvoke\"\n" + - " }\n" + - " }\n" + - " ]\n" + - "}"; - - String sampleKinesisEvent = "{" + - " \"Records\": [" + - " {" + - " \"kinesis\": {" + - " \"kinesisSchemaVersion\": \"1.0\"," + - " \"partitionKey\": \"1\"," + - " \"sequenceNumber\": \"49590338271490256608559692538361571095921575989136588898\"," + - " \"data\": \"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==\"," + - " \"approximateArrivalTimestamp\": 1545084650.987" + - " }," + - " \"eventSource\": \"aws:kinesis\"," + - " \"eventVersion\": \"1.0\"," + - " \"eventID\": \"shardId-000000000006:49590338271490256608559692538361571095921575989136588898\"," + - " \"eventName\": \"aws:kinesis:record\"," + - " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\"," + - " \"awsRegion\": \"us-east-2\"," + - " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"" + - " }," + - " {" + - " \"kinesis\": {" + - " \"kinesisSchemaVersion\": \"1.0\"," + - " \"partitionKey\": \"1\"," + - " \"sequenceNumber\": \"49590338271490256608559692540925702759324208523137515618\"," + - " \"data\": \"VGhpcyBpcyBvbmx5IGEgdGVzdC4=\"," + - " \"approximateArrivalTimestamp\": 1545084711.166" + - " }," + - " \"eventSource\": \"aws:kinesis\"," + - " \"eventVersion\": \"1.0\"," + - " \"eventID\": \"shardId-000000000006:49590338271490256608559692540925702759324208523137515618\"," + - " \"eventName\": \"aws:kinesis:record\"," + - " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\"," + - " \"awsRegion\": \"us-east-2\"," + - " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"" + - " }" + - " ]" + - "}"; - - //https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html - String apiGatewayV2Event = "{\n" + - " \"version\": \"2.0\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"rawPath\": \"/my/path\",\n" + - " \"rawQueryString\": \"parameter1=value1¶meter1=value2¶meter2=value\",\n" + - " \"cookies\": [\n" + - " \"cookie1\",\n" + - " \"cookie2\"\n" + - " ],\n" + - " \"headers\": {\n" + - " \"header1\": \"value1\",\n" + - " \"header2\": \"value1,value2\"\n" + - " },\n" + - " \"queryStringParameters\": {\n" + - " \"parameter1\": \"value1,value2\",\n" + - " \"parameter2\": \"value\"\n" + - " },\n" + - " \"requestContext\": {\n" + - " \"accountId\": \"123456789012\",\n" + - " \"apiId\": \"api-id\",\n" + - " \"authentication\": {\n" + - " \"clientCert\": {\n" + - " \"clientCertPem\": \"CERT_CONTENT\",\n" + - " \"subjectDN\": \"www.example.com\",\n" + - " \"issuerDN\": \"Example issuer\",\n" + - " \"serialNumber\": \"a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1\",\n" + - " \"validity\": {\n" + - " \"notBefore\": \"May 28 12:30:02 2019 GMT\",\n" + - " \"notAfter\": \"Aug 5 09:36:04 2021 GMT\"\n" + - " }\n" + - " }\n" + - " },\n" + - " \"authorizer\": {\n" + - " \"jwt\": {\n" + - " \"claims\": {\n" + - " \"claim1\": \"value1\",\n" + - " \"claim2\": \"value2\"\n" + - " },\n" + - " \"scopes\": [\n" + - " \"scope1\",\n" + - " \"scope2\"\n" + - " ]\n" + - " }\n" + - " },\n" + - " \"domainName\": \"id.execute-api.us-east-1.amazonaws.com\",\n" + - " \"domainPrefix\": \"id\",\n" + - " \"http\": {\n" + - " \"method\": \"POST\",\n" + - " \"path\": \"/my/path\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"sourceIp\": \"IP\",\n" + - " \"userAgent\": \"agent\"\n" + - " },\n" + - " \"requestId\": \"id\",\n" + - " \"routeKey\": \"$default\",\n" + - " \"stage\": \"$default\",\n" + - " \"time\": \"12/Mar/2020:19:03:58 +0000\",\n" + - " \"timeEpoch\": 1583348638390\n" + - " },\n" + - " \"body\": \"Hello from Lambda\",\n" + - " \"pathParameters\": {\n" + - " \"parameter1\": \"value1\"\n" + - " },\n" + - " \"isBase64Encoded\": false,\n" + - " \"stageVariables\": {\n" + - " \"stageVariable1\": \"value1\",\n" + - " \"stageVariable2\": \"value2\"\n" + - " }\n" + - "}"; - - String apiGatewayEvent = "{\n" + - " \"resource\": \"/uppercase2\",\n" + - " \"path\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"headers\": {\n" + - " \"accept\": \"*/*\",\n" + - " \"content-type\": \"application/json\",\n" + - " \"Host\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"User-Agent\": \"curl/7.54.0\",\n" + - " \"X-Amzn-Trace-Id\": \"Root=1-5ece339e-e0595766066d703ec70f1522\",\n" + - " \"X-Forwarded-For\": \"90.37.8.133\",\n" + - " \"X-Forwarded-Port\": \"443\",\n" + - " \"X-Forwarded-Proto\": \"https\"\n" + - " },\n" + - " \"multiValueHeaders\": {\n" + - " \"accept\": [\n" + - " \"*/*\"\n" + - " ],\n" + - " \"content-type\": [\n" + - " \"application/json\"\n" + - " ],\n" + - " \"Host\": [\n" + - " \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\"\n" + - " ],\n" + - " \"User-Agent\": [\n" + - " \"curl/7.54.0\"\n" + - " ],\n" + - " \"X-Amzn-Trace-Id\": [\n" + - " \"Root=1-5ece339e-e0595766066d703ec70f1522\"\n" + - " ],\n" + - " \"X-Forwarded-For\": [\n" + - " \"90.37.8.133\"\n" + - " ],\n" + - " \"X-Forwarded-Port\": [\n" + - " \"443\"\n" + - " ],\n" + - " \"X-Forwarded-Proto\": [\n" + - " \"https\"\n" + - " ]\n" + - " },\n" + - " \"queryStringParameters\": null,\n" + - " \"multiValueQueryStringParameters\": null,\n" + - " \"pathParameters\": null,\n" + - " \"stageVariables\": null,\n" + - " \"requestContext\": {\n" + - " \"resourceId\": \"qf0io6\",\n" + - " \"resourcePath\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"extendedRequestId\": \"NL0A1EokCGYFZOA=\",\n" + - " \"requestTime\": \"27/May/2020:09:32:14 +0000\",\n" + - " \"path\": \"/test/uppercase2\",\n" + - " \"accountId\": \"123456789098\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"stage\": \"test\",\n" + - " \"domainPrefix\": \"fhul32ccy2\",\n" + - " \"requestTimeEpoch\": 1590571934872,\n" + - " \"requestId\": \"b96500aa-f92a-43c3-9360-868ba4053a00\",\n" + - " \"identity\": {\n" + - " \"cognitoIdentityPoolId\": null,\n" + - " \"accountId\": null,\n" + - " \"cognitoIdentityId\": null,\n" + - " \"caller\": null,\n" + - " \"sourceIp\": \"90.37.8.133\",\n" + - " \"principalOrgId\": null,\n" + - " \"accessKey\": null,\n" + - " \"cognitoAuthenticationType\": null,\n" + - " \"cognitoAuthenticationProvider\": null,\n" + - " \"userArn\": null,\n" + - " \"userAgent\": \"curl/7.54.0\",\n" + - " \"user\": null\n" + - " },\n" + - " \"domainName\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"apiId\": \"fhul32ccy2\"\n" + - " },\n" + - " \"body\":\"hello\",\n" + - " \"isBase64Encoded\": false\n" + - "}"; - - String s3Event = "{\n" + - " \"Records\":[\n" + - " {\n" + - " \"eventVersion\":\"2.1\",\n" + - " \"eventSource\":\"aws:s3\",\n" + - " \"awsRegion\":\"us-east-2\",\n" + - " \"eventTime\":\"2020-07-15T21:29:41.365Z\",\n" + - " \"eventName\":\"ObjectCreated:Put\",\n" + - " \"userIdentity\":{\n" + - " \"principalId\":\"AWS:AIxxx\"\n" + - " },\n" + - " \"requestParameters\":{\n" + - " \"sourceIPAddress\":\"xxxx\"\n" + - " },\n" + - " \"responseElements\":{\n" + - " \"x-amz-request-id\":\"xxxx\",\n" + - " \"x-amz-id-2\":\"xxx/=\"\n" + - " },\n" + - " \"s3\":{\n" + - " \"s3SchemaVersion\":\"1.0\",\n" + - " \"configurationId\":\"New Data Delivery\",\n" + - " \"bucket\":{\n" + - " \"name\":\"bucket\",\n" + - " \"ownerIdentity\":{\n" + - " \"principalId\":\"xxx\"\n" + - " },\n" + - " \"arn\":\"arn:aws:s3:::bucket\"\n" + - " },\n" + - " \"object\":{\n" + - " \"key\":\"test/file.geojson\",\n" + - " \"size\":32711,\n" + - " \"eTag\":\"aaaa\",\n" + - " \"sequencer\":\"aaaa\"\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - "}"; - - String apiGatewayEventWithStructuredBody = "{\n" + - " \"resource\": \"/uppercase2\",\n" + - " \"path\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"headers\": {\n" + - " \"accept\": \"*/*\",\n" + - " \"content-type\": \"application/json\",\n" + - " \"Host\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"User-Agent\": \"curl/7.54.0\",\n" + - " \"X-Amzn-Trace-Id\": \"Root=1-5ece339e-e0595766066d703ec70f1522\",\n" + - " \"X-Forwarded-For\": \"90.37.8.133\",\n" + - " \"X-Forwarded-Port\": \"443\",\n" + - " \"X-Forwarded-Proto\": \"https\"\n" + - " },\n" + - " \"multiValueHeaders\": {\n" + - " \"accept\": [\n" + - " \"*/*\"\n" + - " ],\n" + - " \"content-type\": [\n" + - " \"application/json\"\n" + - " ],\n" + - " \"Host\": [\n" + - " \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\"\n" + - " ],\n" + - " \"User-Agent\": [\n" + - " \"curl/7.54.0\"\n" + - " ],\n" + - " \"X-Amzn-Trace-Id\": [\n" + - " \"Root=1-5ece339e-e0595766066d703ec70f1522\"\n" + - " ],\n" + - " \"X-Forwarded-For\": [\n" + - " \"90.37.8.133\"\n" + - " ],\n" + - " \"X-Forwarded-Port\": [\n" + - " \"443\"\n" + - " ],\n" + - " \"X-Forwarded-Proto\": [\n" + - " \"https\"\n" + - " ]\n" + - " },\n" + - " \"queryStringParameters\": null,\n" + - " \"multiValueQueryStringParameters\": null,\n" + - " \"pathParameters\": null,\n" + - " \"stageVariables\": null,\n" + - " \"requestContext\": {\n" + - " \"resourceId\": \"qf0io6\",\n" + - " \"resourcePath\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"extendedRequestId\": \"NL0A1EokCGYFZOA=\",\n" + - " \"requestTime\": \"27/May/2020:09:32:14 +0000\",\n" + - " \"path\": \"/test/uppercase2\",\n" + - " \"accountId\": \"123456789098\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"stage\": \"test\",\n" + - " \"domainPrefix\": \"fhul32ccy2\",\n" + - " \"requestTimeEpoch\": 1590571934872,\n" + - " \"requestId\": \"b96500aa-f92a-43c3-9360-868ba4053a00\",\n" + - " \"identity\": {\n" + - " \"cognitoIdentityPoolId\": null,\n" + - " \"accountId\": null,\n" + - " \"cognitoIdentityId\": null,\n" + - " \"caller\": null,\n" + - " \"sourceIp\": \"90.37.8.133\",\n" + - " \"principalOrgId\": null,\n" + - " \"accessKey\": null,\n" + - " \"cognitoAuthenticationType\": null,\n" + - " \"cognitoAuthenticationProvider\": null,\n" + - " \"userArn\": null,\n" + - " \"userAgent\": \"curl/7.54.0\",\n" + - " \"user\": null\n" + - " },\n" + - " \"domainName\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"apiId\": \"fhul32ccy2\"\n" + - " },\n" + - " \"body\":{\"name\":\"Jim Lahey\"},\n" + - " \"isBase64Encoded\": false\n" + - "}"; - - String apiGatewayEventWithArray = "{\n" + - " \"resource\": \"/uppercase2\",\n" + - " \"path\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"headers\": {\n" + - " \"accept\": \"*/*\",\n" + - " \"content-type\": \"application/json\",\n" + - " \"Host\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"User-Agent\": \"curl/7.54.0\",\n" + - " \"X-Amzn-Trace-Id\": \"Root=1-5ece339e-e0595766066d703ec70f1522\",\n" + - " \"X-Forwarded-For\": \"90.37.8.133\",\n" + - " \"X-Forwarded-Port\": \"443\",\n" + - " \"X-Forwarded-Proto\": \"https\"\n" + - " },\n" + - " \"multiValueHeaders\": {\n" + - " \"accept\": [\n" + - " \"*/*\"\n" + - " ],\n" + - " \"content-type\": [\n" + - " \"application/json\"\n" + - " ],\n" + - " \"Host\": [\n" + - " \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\"\n" + - " ],\n" + - " \"User-Agent\": [\n" + - " \"curl/7.54.0\"\n" + - " ],\n" + - " \"X-Amzn-Trace-Id\": [\n" + - " \"Root=1-5ece339e-e0595766066d703ec70f1522\"\n" + - " ],\n" + - " \"X-Forwarded-For\": [\n" + - " \"90.37.8.133\"\n" + - " ],\n" + - " \"X-Forwarded-Port\": [\n" + - " \"443\"\n" + - " ],\n" + - " \"X-Forwarded-Proto\": [\n" + - " \"https\"\n" + - " ]\n" + - " },\n" + - " \"queryStringParameters\": null,\n" + - " \"multiValueQueryStringParameters\": null,\n" + - " \"pathParameters\": null,\n" + - " \"stageVariables\": null,\n" + - " \"requestContext\": {\n" + - " \"resourceId\": \"qf0io6\",\n" + - " \"resourcePath\": \"/uppercase2\",\n" + - " \"httpMethod\": \"POST\",\n" + - " \"extendedRequestId\": \"NL0A1EokCGYFZOA=\",\n" + - " \"requestTime\": \"27/May/2020:09:32:14 +0000\",\n" + - " \"path\": \"/test/uppercase2\",\n" + - " \"accountId\": \"123456789098\",\n" + - " \"protocol\": \"HTTP/1.1\",\n" + - " \"stage\": \"test\",\n" + - " \"domainPrefix\": \"fhul32ccy2\",\n" + - " \"requestTimeEpoch\": 1590571934872,\n" + - " \"requestId\": \"b96500aa-f92a-43c3-9360-868ba4053a00\",\n" + - " \"identity\": {\n" + - " \"cognitoIdentityPoolId\": null,\n" + - " \"accountId\": null,\n" + - " \"cognitoIdentityId\": null,\n" + - " \"caller\": null,\n" + - " \"sourceIp\": \"90.37.8.133\",\n" + - " \"principalOrgId\": null,\n" + - " \"accessKey\": null,\n" + - " \"cognitoAuthenticationType\": null,\n" + - " \"cognitoAuthenticationProvider\": null,\n" + - " \"userArn\": null,\n" + - " \"userAgent\": \"curl/7.54.0\",\n" + - " \"user\": null\n" + - " },\n" + - " \"domainName\": \"fhul32ccy2.execute-api.eu-west-3.amazonaws.com\",\n" + - " \"apiId\": \"fhul32ccy2\"\n" + - " },\n" + - " \"body\":[{\"name\":\"Jim Lahey\"},{\"name\":\"Ricky\"}],\n" + - " \"isBase64Encoded\": false\n" + - "}"; - - String gwAuthorizerEvent = "{\n" - + " \"type\":\"TOKEN\",\n" - + " \"authorizationToken\":\"allow\",\n" - + " \"methodArn\":\"arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/\"\n" - + "}"; - - @BeforeEach - public void before() throws Exception { - System.clearProperty("MAIN_CLASS"); - System.clearProperty("spring.cloud.function.routing-expression"); - System.clearProperty("spring.cloud.function.definition"); - //this.getEnvironment().clear(); - } - - @Test - public void testAPIGatewayCustomAuthorizerEvent() throws Exception { - System.setProperty("MAIN_CLASS", AuthorizerConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "acceptAuthorizerEvent"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.gwAuthorizerEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("APIGatewayCustomAuthorizerEvent(version=null, type=TOKEN"); - } - - @Test - public void testCollection() throws Exception { - System.setProperty("MAIN_CLASS", SampleConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoStringReactive"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.jsonCollection.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).isEqualTo(this.jsonCollection); - } - - @Test - public void testCollectionPojo() throws Exception { - System.setProperty("MAIN_CLASS", SampleConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoPojoReactive"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.jsonPojoCollection.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).isEqualTo(this.jsonPojoCollection); - } - - @Test - public void testKinesisStringEvent() throws Exception { - System.setProperty("MAIN_CLASS", KinesisConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleKinesisEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("kinesisSchemaVersion"); - } - - @Test - public void testKinesisEvent() throws Exception { - System.setProperty("MAIN_CLASS", KinesisConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputKinesisEvent"); - FunctionInvoker invoker = new FunctionInvoker() { - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - assertThat(context).isNotNull(); - super.handleRequest(input, output, context); - } - }; - - InputStream targetStream = new ByteArrayInputStream(this.sampleKinesisEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, new TestContext()); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("49590338271490256608559692538361571095921575989136588898"); - } - - @Test - public void testKinesisEventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", KinesisConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputKinesisEventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleKinesisEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("49590338271490256608559692538361571095921575989136588898"); - } - - @Test - public void testKinesisEventAsMap() throws Exception { - System.setProperty("MAIN_CLASS", KinesisConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputKinesisEventAsMap"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleKinesisEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("49590338271490256608559692538361571095921575989136588898"); - } - - @Test - public void testSQSStringEvent() throws Exception { - System.setProperty("MAIN_CLASS", SQSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSQSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result.length()).isEqualTo(14); // some additional JSON formatting - } - - @Test - public void testDynamoDb() throws Exception { - System.setProperty("MAIN_CLASS", DynamoDbConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "consume"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.dynamoDbEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - } - - @Test - public void testSQSEvent() throws Exception { - System.setProperty("MAIN_CLASS", SQSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSQSEvent"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSQSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sqs:eu-central-1:123456789012:MyQueue"); - } - - @Test - public void testSQSEventWithConstructorArg() throws Exception { - System.setProperty("MAIN_CLASS", SQSConfiguration.class.getName()); - FunctionInvoker invoker = new FunctionInvoker("inputSQSEvent"); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSQSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sqs:eu-central-1:123456789012:MyQueue"); - } - - @Test - public void testSQSEventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", SQSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSQSEventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSQSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sqs:eu-central-1:123456789012:MyQueue"); - } - - @Test - public void testSQSEventAsMap() throws Exception { - System.setProperty("MAIN_CLASS", SQSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSQSEventAsMap"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSQSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sqs:eu-central-1:123456789012:MyQueue"); - } - - @Test - public void testSNSStringEvent() throws Exception { - System.setProperty("MAIN_CLASS", SNSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSNSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sns"); - } - - @Test - public void testSNSEvent() throws Exception { - System.setProperty("MAIN_CLASS", SNSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSNSEvent"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSNSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sns"); - } - - @Test - public void testSNSEventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", SNSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSNSEventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSNSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sns"); - } - - @Test - public void testSNSEventAsMap() throws Exception { - System.setProperty("MAIN_CLASS", SNSConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputSNSEventAsMap"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleSNSEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("arn:aws:sns"); - } - - @Test - public void testS3StringEvent() throws Exception { - System.setProperty("MAIN_CLASS", S3Configuration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.s3Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("s3SchemaVersion"); - } - - @Test - public void testS3Event() throws Exception { - System.setProperty("MAIN_CLASS", S3Configuration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputS3Event"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.s3Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("ObjectCreated:Put"); - } - - @Test - public void testS3EventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", S3Configuration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputS3EventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.s3Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("ObjectCreated:Put"); - } - - @Test - public void testS3EventAsMap() throws Exception { - System.setProperty("MAIN_CLASS", S3Configuration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputS3EventAsMap"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.s3Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("s3SchemaVersion"); - } - - - @Test - public void testLBEventStringInOut() throws Exception { - System.setProperty("MAIN_CLASS", LBConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleLBEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"Hello from ELB\""); - } - - @Test - public void testS3EventReactive() throws Exception { - System.setProperty("MAIN_CLASS", S3Configuration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoStringFlux"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.s3Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - assertThat(result).contains("s3SchemaVersion"); - } - - @Test - public void testLBEvent() throws Exception { - System.setProperty("MAIN_CLASS", LBConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputLBEvent"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleLBEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"Hello from ELB\""); - } - - @Test - public void testLBEventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", LBConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputLBEventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.sampleLBEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, Mockito.mock(Context.class)); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"Hello from ELB\""); - } - - @Test - public void testLBEventInOut() throws Exception { - System.setProperty("MAIN_CLASS", LBConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputOutputLBEvent"); - FunctionInvoker invoker = new FunctionInvoker() { - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - assertThat(context).isNotNull(); - super.handleRequest(input, output, context); - } - }; - - InputStream targetStream = new ByteArrayInputStream(this.sampleLBEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, new TestContext()); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("Hello from ELB"); - } - - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayStringEventBody() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "uppercase"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"HELLO\""); - - System.clearProperty("spring.cloud.function.definition"); - System.setProperty("spring.cloud.function.routing-expression", "'uppercase'"); - invoker = new FunctionInvoker(); - targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - result = this.mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"HELLO\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayPojoReturninPojo() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "uppercasePojoReturnPojo"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEventWithStructuredBody.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map response = mapper.readValue(output.toByteArray(), Map.class); - Person person = mapper.readValue((String) response.get("body"), Person.class); - assertThat(person.getName()).isEqualTo("JIM LAHEY"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayPojoReturninPojoReactive() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "uppercasePojoReturnPojoReactive"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEventWithArray.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map response = mapper.readValue(output.toByteArray(), Map.class); - assertThat(response.get("body").toString()).isEqualTo("[{\"name\":\"JIM LAHEY\"},{\"name\":\"RICKY\"}]"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayPojoEventBody() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "uppercasePojo"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEventWithStructuredBody.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"JIM LAHEY\""); - - System.clearProperty("spring.cloud.function.definition"); - System.setProperty("spring.cloud.function.routing-expression", "'uppercasePojo'"); - invoker = new FunctionInvoker(); - targetStream = new ByteArrayInputStream(this.apiGatewayEventWithStructuredBody.getBytes()); - output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - result = this.mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"JIM LAHEY\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayEvent() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputApiEvent"); - FunctionInvoker invoker = new FunctionInvoker() { - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - assertThat(context).isNotNull(); - super.handleRequest(input, output, context); - } - }; - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, new TestContext()); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - System.out.println(result); - assertThat(result.get("body")).isEqualTo("\"hello\""); - - System.clearProperty("spring.cloud.function.definition"); - System.setProperty("spring.cloud.function.routing-expression", "'inputApiEvent'"); - invoker = new FunctionInvoker(); - targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - result = this.mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"hello\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayV2Event() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputApiV2Event"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayV2Event.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - System.out.println(result); - assertThat(result.get("body")).isEqualTo("\"Hello from Lambda\""); - - System.clearProperty("spring.cloud.function.definition"); - System.setProperty("spring.cloud.function.routing-expression", "'inputApiV2Event'"); - invoker = new FunctionInvoker(); - targetStream = new ByteArrayInputStream(this.apiGatewayV2Event.getBytes()); - output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - result = this.mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"Hello from Lambda\""); - } - - @Test - public void testResponseBase64Encoded() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoStringMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - JsonMapper mapper = new JacksonMapper(new ObjectMapper()); - - String result = new String(output.toByteArray(), StandardCharsets.UTF_8); - Map resultMap = mapper.fromJson(result, Map.class); - assertThat((boolean) resultMap.get(AWSLambdaUtils.IS_BASE64_ENCODED)).isTrue(); - String body = new String(Base64.getDecoder().decode((String) resultMap.get(AWSLambdaUtils.BODY)), StandardCharsets.UTF_8); - assertThat(body).isEqualTo("hello"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayAsSupplier() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "supply"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - System.out.println(result); - assertThat(result.get("body")).isEqualTo("\"boom\""); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testApiGatewayInAndOutInputStream() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoInputStreamToString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("hello"); - Map headers = (Map) result.get("headers"); - assertThat(headers).isNotEmpty(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testApiGatewayInAndOutInputStreamMsg() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "echoInputStreamMsgToString"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("hello"); - Map headers = (Map) result.get("headers"); - assertThat(headers).isNotEmpty(); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayInAndOut() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputOutputApiEvent"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("hello"); - Map headers = (Map) result.get("headers"); - assertThat(headers.get("foo")).isEqualTo("bar"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayInAndOutV2() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputOutputApiEventV2"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("hello"); - Map headers = (Map) result.get("headers"); - assertThat(headers.get("foo")).isEqualTo("bar"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayEventAsMessage() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputApiEventAsMessage"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - System.out.println(result); - assertThat(result.get("body")).isEqualTo("\"hello\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayEventAsMap() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "inputApiEventAsMap"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - System.out.println(result); - assertThat(result.get("body")).isEqualTo("\"hello\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayEventConsumer() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "consume"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"OK\""); - } - - @SuppressWarnings("rawtypes") - @Test - public void testApiGatewayWithMonoVoidAsReturn() throws Exception { - System.setProperty("MAIN_CLASS", ApiGatewayConfiguration.class.getName()); - System.setProperty("spring.cloud.function.definition", "reactiveWithVoidReturn"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"OK\""); - } - - @Test - public void testWithDefaultRoutingFailure() throws Exception { - System.setProperty("MAIN_CLASS", SampleConfiguration.class.getName()); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - - try { - invoker.handleRequest(targetStream, output, null); - fail(); - } - catch (Exception e) { - // TODO: handle exception - } - } - - @SuppressWarnings("rawtypes") - @Test - public void testWithDefaultRouting() throws Exception { - System.setProperty("MAIN_CLASS", SampleConfiguration.class.getName()); - System.setProperty("spring.cloud.function.routing-expression", "'reverse'"); - FunctionInvoker invoker = new FunctionInvoker(); - - InputStream targetStream = new ByteArrayInputStream(this.apiGatewayEvent.getBytes()); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - invoker.handleRequest(targetStream, output, null); - - Map result = mapper.readValue(output.toByteArray(), Map.class); - assertThat(result.get("body")).isEqualTo("\"olleh\""); - } - - @EnableAutoConfiguration - @Configuration - public static class AuthorizerConfiguration { - @Bean - public Function acceptAuthorizerEvent() { - return v -> v.toString(); - } - } - - @EnableAutoConfiguration - @Configuration - public static class DynamoDbConfiguration { - @Bean - public Consumer consume() { - return event -> event.getRecords().forEach(System.out::println); - } - } - - @EnableAutoConfiguration - @Configuration - public static class SampleConfiguration { - @Bean - public Function echoString() { - return v -> v; - } - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function, Flux> echoStringReactive() { - return v -> v; - } - - @Bean - public Function, Flux> echoPojoReactive() { - return v -> v; - } - } - - @EnableAutoConfiguration - @Configuration - public static class KinesisConfiguration { - @Bean - public Function echoString() { - return v -> v; - } - - @Bean - public Function inputKinesisEvent() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputKinesisEventAsMessage() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputKinesisEventAsMap() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - } - - @EnableAutoConfiguration - @Configuration - public static class SQSConfiguration { - @Bean - public Function echoString() { - return v -> { - System.out.println("Echo: " + v); - return v.toString(); - }; - } - - @Bean - public Function inputSQSEvent() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputSQSEventAsMessage() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputSQSEventAsMap() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public MyCustomMessageConverter messageConverter() { - return new MyCustomMessageConverter(); - } - } - - public static class MyCustomMessageConverter extends AbstractMessageConverter { - - public MyCustomMessageConverter() { - super(new MimeType("*", "*")); - } - - @Override - protected boolean supports(Class clazz) { - return (Person.class.equals(clazz)); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, Object conversionHint) { - Object payload = message.getPayload(); - String v = payload instanceof String ? (String) payload : new String((byte[]) payload); - Person person = new Person(); - person.setName(v.substring(0, 10)); - return person; - } - } - - @EnableAutoConfiguration - @Configuration - public static class SNSConfiguration { - @Bean - public Function echoString() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function inputSNSEvent() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputSNSEventAsMessage() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - - @Bean - public Function, String> inputSNSEventAsMap() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - } - - @EnableAutoConfiguration - @Configuration - public static class S3Configuration { - @Bean - public Function echoString() { - return v -> v; - } - - @Bean - public Function, Flux> echoStringFlux() { - return v -> v; - } - - @Bean - public Function inputS3Event(JsonMapper jsonMapper) { - return v -> { - System.out.println("Received: " + v); - return v.getRecords().get(0).getEventName(); - }; - } - - @Bean - public Function, String> inputS3EventAsMessage(JsonMapper jsonMapper) { - return m -> { - System.out.println("Received: " + m); - return m.getPayload().getRecords().get(0).getEventName(); - }; - } - - @Bean - public Function, String> inputS3EventAsMap() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - } - - @EnableAutoConfiguration - @Configuration - public static class LBConfiguration { - @Bean - public Function echoString() { - return v -> v; - } - - @Bean - public Function inputLBEvent() { - return v -> { - System.out.println("Received: " + v); - return v.getBody(); - }; - } - - @Bean - public Function inputOutputLBEvent() { - return v -> { - ApplicationLoadBalancerResponseEvent response = new ApplicationLoadBalancerResponseEvent(); - response.setBody(v.getBody()); - return response; - }; - } - - @Bean - public Function, String> inputLBEventAsMessage(JsonMapper jsonMapper) { - return message -> { - System.out.println("Received: " + message); - assertThat(message.getHeaders().get(AWSLambdaUtils.AWS_CONTEXT)).isNotNull(); - return message.getPayload().getBody(); - }; - } - - @Bean - public Function, String> inputLBEventAsMap() { - return v -> { - System.out.println("Received: " + v); - return v.toString(); - }; - } - } - - @EnableAutoConfiguration - @Configuration - public static class ApiGatewayConfiguration { - - @Bean - public Supplier supply() { - return () -> "boom"; - } - - @Bean - public Function, Message> echoStringMessage() { - return m -> { - String encodedPayload = Base64.getEncoder().encodeToString(m.getPayload().getBytes(StandardCharsets.UTF_8)); - return MessageBuilder.withPayload(encodedPayload).setHeader("isBase64Encoded", true).build(); - }; - } - - - @Bean - public Consumer consume() { - return v -> System.out.println(v); - } - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function, Mono> reactiveWithVoidReturn() { - return v -> Mono.empty(); - } - - @Bean - public Function uppercasePojo() { - return v -> { - return v.getName().toUpperCase(); - }; - } - - @Bean - public Function uppercasePojoReturnPojo() { - return v -> { - Person p = new Person(); - p.setName(v.getName().toUpperCase()); - return p; - }; - } - - @Bean - public Function, Flux> uppercasePojoReturnPojoReactive() { - return flux -> flux.map(v -> { - Person p = new Person(); - p.setName(v.getName().toUpperCase()); - return p; - }); - } - - @Bean - public Function inputApiEvent() { - return v -> { - return v.getBody(); - }; - } - - @Bean - - public Function echoInputStreamToString() { - return is -> { - try { - String result = StreamUtils.copyToString(is, StandardCharsets.UTF_8); - return result; - } - catch (Exception e) { - throw new RuntimeException(e); - } - }; - } - - @Bean - - public Function, String> echoInputStreamMsgToString() { - return msg -> { - try { - String result = StreamUtils.copyToString(msg.getPayload(), StandardCharsets.UTF_8); - return result; - } - catch (Exception e) { - throw new RuntimeException(e); - } - }; - } - - @Bean - public Function inputOutputApiEvent() { - return v -> { - APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); - response.setBody(v.getBody()); - response.setStatusCode(200); - response.setHeaders(Collections.singletonMap("foo", "bar")); - return response; - }; - } - - @Bean - public Function inputOutputApiEventV2() { - return v -> { - APIGatewayV2HTTPResponse response = new APIGatewayV2HTTPResponse(); - response.setBody(v.getBody()); - response.setStatusCode(200); - response.setHeaders(Collections.singletonMap("foo", "bar")); - return response; - }; - } - - @Bean - public Function inputOutputApiEventException() { - return v -> { - throw new IllegalStateException("Intentional"); - }; - } - - @Bean - public Function inputApiV2Event() { - return v -> { - return v.getBody(); - }; - } - - @Bean - public Function, String> inputApiEventAsMessage() { - return v -> { - return v.getPayload().getBody(); - }; - } - - @Bean - public Function, String> inputApiEventAsMap() { - return v -> { - String body = (String) v.get("body"); - return body; - }; - } - } - - public static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/TestContext.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/TestContext.java deleted file mode 100644 index 6af6b78f7..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-aws/src/test/java/org/springframework/cloud/function/adapter/aws/TestContext.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2019-2022 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 com.amazonaws.services.lambda.runtime.ClientContext; -import com.amazonaws.services.lambda.runtime.CognitoIdentity; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.LambdaLogger; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class TestContext implements Context { - - @Override - public String getAwsRequestId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLogGroupName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLogStreamName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getFunctionName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getFunctionVersion() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getInvokedFunctionArn() { - // TODO Auto-generated method stub - return null; - } - - @Override - public CognitoIdentity getIdentity() { - // TODO Auto-generated method stub - return null; - } - - @Override - public ClientContext getClientContext() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRemainingTimeInMillis() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getMemoryLimitInMB() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public LambdaLogger getLogger() { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/README.adoc b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/README.adoc deleted file mode 100644 index 87dee4f61..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/README.adoc +++ /dev/null @@ -1,11 +0,0 @@ -=== Introduction - -Light weight Azure Function forwarding proxy which can deploy any existing Spring Boot web application as Azure Functions. -Infernally uses the Azure Http Trigger mapping. - -This module is identified as the only additional dependency to the existing web-app. - -A sample is provided in https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-web[azure-web sample] - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/pom.xml deleted file mode 100644 index f65f14857..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - 4.0.0 - spring-cloud-function-adapter-azure-web - jar - spring-cloud-function-adapter-azure-web - Azure Function Adapter for Spring Cloud Function - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - - UTF-8 - UTF-8 - 17 - 3.0.0 - 1.0.0 - - - - com.google.code.findbugs - annotations - 3.0.1 - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.cloud - spring-cloud-function-serverless-web - - - org.springframework.boot - spring-boot-autoconfigure - - - com.microsoft.azure.functions - azure-functions-java-library - ${azure.functions.java.core.version} - - - - com.microsoft.azure.functions - azure-functions-java-spi - ${azure.functions.java.spi.version} - - - jakarta.servlet - jakarta.servlet-api - provided - - - - com.fasterxml.jackson.core - jackson-databind - - - org.springframework - spring-webmvc - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-web - test - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvoker.java deleted file mode 100644 index 08c501152..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvoker.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - -import java.util.Map.Entry; -import java.util.Optional; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; -import com.microsoft.azure.functions.HttpStatus; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; -import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.serverless.web.ProxyHttpServletRequest; -import org.springframework.cloud.function.serverless.web.ProxyHttpServletResponse; -import org.springframework.cloud.function.serverless.web.ProxyMvc; -import org.springframework.cloud.function.utils.FunctionClassUtils; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * - * @author Christian Tzolov - * @author Oleg Zhurakousky - * - */ -public class AzureWebProxyInvoker implements FunctionInstanceInjector { - - private static Log logger = LogFactory.getLog(AzureWebProxyInvoker.class); - - private static final String AZURE_WEB_ADAPTER_NAME = "AzureWebAdapter"; - private static final String AZURE_WEB_ADAPTER_ROUTE = AZURE_WEB_ADAPTER_NAME - + "/{e?}/{e2?}/{e3?}/{e4?}/{e5?}/{e6?}/{e7?}/{e8?}/{e9?}/{e10?}/{e11?}/{e12?}/{e13?}/{e14?}/{e15?}"; - - private ProxyMvc mvc; - - private ServletContext servletContext; - - @Override - public T getInstance(Class functionClass) throws Exception { - this.initialize(); - return (T) this; - } - - /** - * Because the getInstance is called by Azure Java Function on every function request we need to cache the Spring - * context initialization on the first function call. - * @throws ServletException error. - */ - private void initialize() throws ServletException { - synchronized (AzureWebProxyInvoker.class.getName()) { - if (mvc == null) { - Class startClass = FunctionClassUtils.getStartClass(); - this.mvc = ProxyMvc.INSTANCE(startClass); - } - } - } - - private HttpServletRequest prepareRequest(HttpRequestMessage> request) { - - int pathOffset = request.getUri().getPath().indexOf(AZURE_WEB_ADAPTER_NAME) + AZURE_WEB_ADAPTER_NAME.length(); - - String path = request.getUri().getPath().substring(pathOffset); - - ProxyHttpServletRequest httpRequest = new ProxyHttpServletRequest(servletContext, - request.getHttpMethod().toString(), path); - - request.getBody().ifPresent(body -> { - httpRequest.setContent(body.getBytes()); - }); - - if (!CollectionUtils.isEmpty(request.getQueryParameters())) { - httpRequest.setParameters(request.getQueryParameters()); - } - - if (!CollectionUtils.isEmpty(request.getHeaders())) { - for (Entry entry : request.getHeaders().entrySet()) { - httpRequest.addHeader(entry.getKey(), entry.getValue()); - } - } - - return httpRequest; - } - - @FunctionName(AZURE_WEB_ADAPTER_NAME) - public HttpResponseMessage execute( - @HttpTrigger(name = "req", methods = { HttpMethod.GET, - HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS, route = AZURE_WEB_ADAPTER_ROUTE) HttpRequestMessage> request, - ExecutionContext context) { - - context.getLogger().info("Request body is: " + request.getBody().orElse("[empty]")); - - HttpServletRequest httpRequest = this.prepareRequest(request); - - ProxyHttpServletResponse httpResponse = new ProxyHttpServletResponse(); - try { - this.mvc.service(httpRequest, httpResponse); - - Builder responseBuilder = request.createResponseBuilder(HttpStatus.OK); - for (String headerName : httpResponse.getHeaderNames()) { - responseBuilder.header(headerName, httpResponse.getHeader(headerName)); - } - - String responseString = httpResponse.getContentAsString(); - if (StringUtils.hasText(responseString)) { - if (logger.isDebugEnabled()) { - logger.debug("Response: " + responseString); - } - responseBuilder.body(responseString); - } // TODO: what to do with bodyless response? - - return responseBuilder.build(); - } - catch (Exception e) { - e.printStackTrace(); - throw new IllegalStateException(e); - } - - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector deleted file mode 100644 index e01d42baf..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.adapter.azure.web.AzureWebProxyInvoker \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/application.properties b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/application.properties deleted file mode 100644 index d6705c881..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.banner.location=classpath:/spring-azure-function-banner.txt diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/spring-azure-function-banner.txt b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/spring-azure-function-banner.txt deleted file mode 100644 index 32225b776..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/main/resources/spring-azure-function-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - ____ _ _ _____ _ _ - / ___| _ __ _ __(_)_ __ __ _ / \ _____ _ _ __ ___ | ___| _ _ __ ___| |_(_) ___ _ __ ___ - \___ \| '_ \| '__| | '_ \ / _` | / _ \ |_ / | | | '__/ _ \ | |_ | | | | '_ \ / __| __| |/ _ \| '_ \/ __| - ___) | |_) | | | | | | | (_| | / ___ \ / /| |_| | | | __/ | _|| |_| | | | | (__| |_| | (_) | | | \__ \ - |____/| .__/|_| |_|_| |_|\__, | /_/ \_\/___|\__,_|_| \___| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/ - |_| |___/ -${application.title} ${application.version} -Powered by Spring Boot ${spring-boot.version} and Azure Functions \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvokerTests.java deleted file mode 100644 index 55d79eab1..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/AzureWebProxyInvokerTests.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; -import com.microsoft.azure.functions.HttpStatus; -import com.microsoft.azure.functions.HttpStatusType; -import org.junit.jupiter.api.Test; - -public class AzureWebProxyInvokerTests { - - @Test - public void test() throws Exception { - System.setProperty("MAIN_CLASS", PetStoreSpringAppConfig.class.getName()); - AzureWebProxyInvoker proxyInvoker = new AzureWebProxyInvoker(); - AzureWebProxyInvoker instance = proxyInvoker.getInstance(AzureWebProxyInvoker.class); - - HttpRequestMessageStub> request = new HttpRequestMessageStub>(); - - request.setHttpMethod(HttpMethod.GET); - - request.setUri(new URI( - "http://localhost:7072/api/AzureWebAdapter/pets")); - - request.setBody(Optional.of("{\"id\":\"535932f1-d18b-488a-ad8f-8d50b9678492\"" + - "\"breed\":\"Beagle\",\"name\":\"Murphy\",\"dateOfBirth\":1591682824313}")); - - HttpResponseMessage response = instance.execute(request, new TestExecutionContext("execute")); - - System.out.println(response.getBody()); - - } - - public static class HttpRequestMessageStub implements HttpRequestMessage { - - private URI uri; - private HttpMethod httpMethod; - private Map headers; - private Map queryParameters; - private I body; - - public void setUri(URI uri) { - this.uri = uri; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public void setQueryParameters(Map queryParameters) { - this.queryParameters = queryParameters; - } - - public void setBody(I body) { - this.body = body; - } - - @Override - public URI getUri() { - return this.uri; - } - - @Override - public HttpMethod getHttpMethod() { - return this.httpMethod; - } - - @Override - public Map getHeaders() { - return this.headers; - } - - @Override - public Map getQueryParameters() { - return this.queryParameters; - } - - @Override - public I getBody() { - return this.body; - } - - @Override - public HttpResponseMessage.Builder createResponseBuilder(HttpStatusType status) { - return new BuilderStub().status(status); - } - - @Override - public Builder createResponseBuilder(HttpStatus status) { - return new BuilderStub().status(status); - } - - } - - public static class BuilderStub implements Builder { - - private HttpStatusType status; - private Map headers = new HashMap<>(); - private Object body; - - @Override - public Builder status(HttpStatusType status) { - this.status = status; - return this; - } - - @Override - public Builder header(String key, String value) { - headers.put(key, value); - return this; - } - - @Override - public Builder body(Object body) { - this.body = body; - return this; - } - - @Override - public HttpResponseMessage build() { - return new HttpResponseMessageStub(this.status, this.headers, this.body); - } - - } - - public static class HttpResponseMessageStub implements HttpResponseMessage { - - private HttpStatusType status; - private Map headers = new HashMap<>(); - private Object body; - - HttpResponseMessageStub(HttpStatusType status, Map headers, - Object body) { - this.status = status; - this.headers = headers; - this.body = body; - } - - @Override - public HttpStatusType getStatus() { - return this.status; - } - - @Override - public String getHeader(String key) { - return this.headers.get(key); - } - - @Override - public Object getBody() { - return this.body; - } - - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/Pet.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/Pet.java deleted file mode 100644 index 1db16446f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/Pet.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - -import java.util.Date; - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetData.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetData.java deleted file mode 100644 index 59989bf8a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetData.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt(Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR)); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetStoreSpringAppConfig.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetStoreSpringAppConfig.java deleted file mode 100644 index 7e8471ca9..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetStoreSpringAppConfig.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - -import java.io.IOException; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -@Configuration -@Import({ PetsController.class }) -public class PetStoreSpringAppConfig { - /* - * Create required HandlerMapping, to avoid several default HandlerMapping - * instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter - * instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - @Bean - public Filter filter() { - return new Filter() { - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - System.out.println("FILTER ===> Hello from: " + request.getLocalAddr()); - chain.doFilter(request, response); - } - }; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetsController.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetsController.java deleted file mode 100644 index 7a99c53e8..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/PetsController.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2023-2023 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.web; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -@RestController -@EnableWebMvc -public class PetsController { - @RequestMapping(path = "/pets", method = RequestMethod.POST) - public Pet createPet(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @RequestMapping(path = "/pets", method = RequestMethod.GET) - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - System.out.println("=====> EXECUTING"); - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET) - public Pet listPets() { - System.out.println("=====> Getting pet by id"); - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/TestExecutionContext.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/TestExecutionContext.java deleted file mode 100644 index bbdf32f56..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web/src/test/java/org/springframework/cloud/function/adapter/azure/web/TestExecutionContext.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.adapter.azure.web; - -import java.util.UUID; -import java.util.logging.Logger; - -import com.microsoft.azure.functions.ExecutionContext; - -public class TestExecutionContext implements ExecutionContext { - - private String name; - - public TestExecutionContext(String name) { - this.name = name; - } - - @Override - public Logger getLogger() { - return Logger.getLogger(TestExecutionContext.class.getName()); - } - - @Override - public String getInvocationId() { - return UUID.randomUUID().toString(); - } - - @Override - public String getFunctionName() { - return this.name; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/.jdk8 b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc deleted file mode 100644 index 74fbb3535..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc +++ /dev/null @@ -1,17 +0,0 @@ -//// -DO NOT EDIT THIS FILE. IT WAS GENERATED. -Manual changes to this file will be lost when it is generated again. -Edit the files in the src/main/asciidoc/ directory instead. -//// - -This project provides an adapter layer for a Spring Cloud Function application onto Azure. -You can write an app with a single `@Bean` of type `Function` and it will be deployable in Azure if you get the JAR file laid out right. - -== Sample Functions - -- ../../spring-cloud-function-samples/function-sample-azure-http-trigger[Azure HTTP Trigger (Maven)] -- ../../spring-cloud-function-samples/function-sample-azure-http-trigger-gradle[Azure HTTP Trigger (Gradle)] -- ../../spring-cloud-function-samples/function-sample-azure-blob-trigger[Azure Blob Trigger (Maven)] -- ../../spring-cloud-function-samples/function-sample-azure-timer-trigger[Azure Timer Trigger (Maven)] -- ../../spring-cloud-function-samples/function-sample-azure-kafka-trigger[Azure Kafka Trigger & Output Binding (Maven)] -- ../../spring-cloud-function-samples/function-sample-azure/[(Legacy - FunctionInvoker) Azure HTTP Trigger (Maven)] 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 deleted file mode 100644 index 0808fd70d..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/pom.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-adapter-azure - jar - - spring-cloud-function-adapter-azure - Azure Function Adapter for Spring Cloud Function - - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - - - UTF-8 - UTF-8 - 17 - - 3.0.0 - 1.0.0 - - - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.boot - spring-boot-starter - - - spring-boot-starter-logging - org.springframework.boot - - - - - io.projectreactor - reactor-core - - - org.springframework.boot - spring-boot-starter-test - test - - - - com.microsoft.azure.functions - azure-functions-java-library - ${azure.functions.java.core.version} - - - - com.microsoft.azure.functions - azure-functions-java-spi - ${azure.functions.java.spi.version} - - - - org.slf4j - slf4j-log4j12 - 2.0.7 - test - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionInstanceInjector.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionInstanceInjector.java deleted file mode 100644 index 999d24c01..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionInstanceInjector.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2021-2022 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.Map; - -import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.ResourceBanner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.WebApplicationType; -import org.springframework.cloud.function.utils.FunctionClassUtils; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.util.ClassUtils; -import org.springframework.util.CollectionUtils; - -/** - * The instance factory used by the Spring framework to initialize Azure function instance. It is waived with the Azure - * Java Worker through the META-INFO/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector service - * hook. The Azure Java Worker delegates scans the classpath for service definition and delegates the function class - * creation to this instance factory. - * @author Christian Tzolov - * @since 3.2.9 - */ -public class AzureFunctionInstanceInjector implements FunctionInstanceInjector { - - private static Log logger = LogFactory.getLog(AzureFunctionInstanceInjector.class); - - private static ConfigurableApplicationContext APPLICATION_CONTEXT; - - /** - * This method is called by the Azure Java Worker on every function invocation. The Worker sends in the classes - * annotated with @FunctionName annotations and allows the Spring framework to initialize the function instance as a - * Spring Bean and return the instance. Then the Worker uses the created instance to invoke the function. - * @param functionClass the class that contains customer Azure functions (e.g. @FunctionName annotated ) - * @param customer Azure functions class type - * @return the instance that will be invoked on by azure functions java worker - * @throws Exception any exception that is thrown by the Spring framework during instance creation - */ - @Override - public T getInstance(Class functionClass) throws Exception { - try { - // Backward compatibility workaround. If the function class is of type FunctionInvoker then create plain - // Java instance and delegate to FunctionInvoker adaptor approach. - if (ClassUtils.isAssignable(FunctionInvoker.class, functionClass)) { - return functionClass.getDeclaredConstructor().newInstance(); - } - - initialize(); - - Map azureFunctionBean = APPLICATION_CONTEXT.getBeansOfType(functionClass); - if (CollectionUtils.isEmpty(azureFunctionBean)) { - throw new IllegalStateException( - "Failed to retrieve Bean instance for: " + functionClass - + ". The class should be annotated with @Component to let the Spring framework initialize it!"); - } - return azureFunctionBean.entrySet().iterator().next().getValue(); - } - catch (Exception e) { - if (APPLICATION_CONTEXT != null) { - APPLICATION_CONTEXT.close(); - } - throw new IllegalStateException("Failed to initialize", e); - } - } - - /** - * Create a static Application Context instance shared between multiple function invocations. - */ - private static void initialize() { - synchronized (AzureFunctionInstanceInjector.class.getName()) { - if (APPLICATION_CONTEXT == null) { - Class springConfigurationClass = FunctionClassUtils.getStartClass(); - logger.info("Initializing: " + springConfigurationClass); - APPLICATION_CONTEXT = springApplication(springConfigurationClass).run(); - } - } - } - - private static SpringApplication springApplication(Class configurationClass) { - SpringApplication application = new org.springframework.cloud.function.context.FunctionalSpringApplication( - configurationClass); - application.setWebApplicationType(WebApplicationType.NONE); - application.setBanner(new ResourceBanner( - new DefaultResourceLoader().getResource("classpath:/spring-azure-function-banner.txt"))); - return application; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionUtil.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionUtil.java deleted file mode 100644 index 860e94a23..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureFunctionUtil.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2023-2023 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.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @author Christian Tzolov - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 4.0 - */ -public final class AzureFunctionUtil { - - /** - * Message header key name used to store and extract the ExecutionContext. - */ - public static String EXECUTION_CONTEXT = "executionContext"; - - private AzureFunctionUtil() { - }; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Object enhanceInputIfNecessary(Object input, ExecutionContext executionContext) { - if (input == null) { // Supplier - return input; - } - if (input instanceof Publisher) { - return Flux.from((Publisher) input).map(item -> { - if (item instanceof Message) { - return MessageBuilder.fromMessage((Message) item) - .setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - else { - return constructInputMessageFromItem(input, executionContext); - } - }); - } - else if (input instanceof Message) { - return MessageBuilder.fromMessage((Message) input) - .setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - else if (input instanceof Iterable) { - return Flux.fromIterable((Iterable) input).map(item -> { - return constructInputMessageFromItem(item, executionContext); - }); - } - return constructInputMessageFromItem(input, executionContext); - } - - private static Message constructInputMessageFromItem(Object input, ExecutionContext executionContext) { - MessageBuilder messageBuilder = null; - if (input instanceof HttpRequestMessage) { - HttpRequestMessage requestMessage = (HttpRequestMessage) input; - Object payload = requestMessage.getHttpMethod() != null - && requestMessage.getHttpMethod().equals(HttpMethod.GET) - ? requestMessage.getQueryParameters() - : requestMessage.getBody(); - - if (payload == null) { - payload = Optional.empty(); - } - messageBuilder = MessageBuilder.withPayload(payload).copyHeaders(getHeaders(requestMessage)); - } - else { - messageBuilder = MessageBuilder.withPayload(input); - } - return messageBuilder.setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - - private static 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); - } - -} 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 deleted file mode 100644 index decdd24c2..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2021-2022 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.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; -import com.microsoft.azure.functions.HttpStatus; -import com.microsoft.azure.functions.OutputBinding; -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.boot.SpringApplication; -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.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.cloud.function.context.config.JsonMessageConverter; -import org.springframework.cloud.function.context.config.SmartCompositeMessageConverter; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.utils.FunctionClassUtils; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * @param input type - * @param result type - * @author Oleg Zhurakousky - * @author Chris Bono - * @author Christian Tzolov - * - * @since 3.2 - * - * @deprecated since 4.0.0 in favor of the dependency injection implementation {@link AzureFunctionInstanceInjector}. - * Follow the official documentation for further information. - */ -@Deprecated -public class FunctionInvoker { - - private static Log logger = LogFactory.getLog(FunctionInvoker.class); - - private static String EXECUTION_CONTEXT = "executionContext"; - - private static FunctionCatalog FUNCTION_CATALOG; - - private static ConfigurableApplicationContext APPLICATION_CONTEXT; - - private static JsonMapper OBJECT_MAPPER; - - public FunctionInvoker(Class configurationClass) { - try { - initialize(configurationClass); - } - catch (Exception e) { - this.close(); - throw new IllegalStateException("Failed to initialize", e); - } - } - - public FunctionInvoker() { - this(FunctionClassUtils.getStartClass()); - } - - public O handleRequest(ExecutionContext context) { - return this.handleRequest(null, context); - } - - public void close() { - FUNCTION_CATALOG = null; - } - - public void handleOutput(I input, OutputBinding binding, - ExecutionContext context) { - O result = handleRequest(input, context); - binding.setValue(result); - } - - private FunctionInvocationWrapper discoverFunction(String functionDefinition) { - FunctionInvocationWrapper function = FUNCTION_CATALOG.lookup(functionDefinition); - if (function != null && StringUtils.hasText(functionDefinition) - && !function.getFunctionDefinition().equals(functionDefinition)) { - this.registerFunction(functionDefinition); - function = FUNCTION_CATALOG.lookup(functionDefinition); - } - else if (function == null && StringUtils.hasText(functionDefinition) - && APPLICATION_CONTEXT.containsBean(functionDefinition)) { - this.registerFunction(functionDefinition); - function = FUNCTION_CATALOG.lookup(functionDefinition); - } - return function; - } - - public O handleRequest(I input, ExecutionContext executionContext) { - String functionDefinition = executionContext.getFunctionName(); - FunctionInvocationWrapper function = this.discoverFunction(functionDefinition); - Object enhancedInput = enhanceInputIfNecessary(input, executionContext); - - Object functionResult = function.apply(enhancedInput); - - if (functionResult instanceof Publisher) { - return postProcessReactiveFunctionResult(input, enhancedInput, (Publisher) functionResult, function, - executionContext); - } - return postProcessImperativeFunctionResult(input, enhancedInput, functionResult, function, executionContext); - } - - /** - * Post-processes the result from a non-reactive function invocation before returning it to the Azure runtime. The - * default behavior is to {@link #convertOutputIfNecessary possibly convert} the result. - * - *

- * Provides a hook for custom function invokers to extend/modify the function results handling. - * - * @param rawInputs the inputs passed in from the Azure runtime - * @param functionInputs the actual inputs used for the function invocation; may be {@link #enhanceInputIfNecessary - * different} from the {@literal rawInputs} - * @param functionResult the result from the function invocation - * @param function the invoked function - * @param executionContext the Azure execution context - * @return the possibly modified function results - */ - @SuppressWarnings("unchecked") - protected O postProcessImperativeFunctionResult(I rawInputs, Object functionInputs, Object functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext) { - return (O) this.convertOutputIfNecessary(rawInputs, functionResult); - } - - /** - * Post-processes the result from a reactive function invocation before returning it to the Azure runtime. The - * default behavior is to delegate to {@link #postProcessMonoFunctionResult} or - * {@link #postProcessFluxFunctionResult} based on the result type. - * - *

- * Provides a hook for custom function invokers to extend/modify the function results handling. - * - * @param rawInputs the inputs passed in from the Azure runtime - * @param functionInputs the actual inputs used for the function invocation; may be {@link #enhanceInputIfNecessary - * different} from the {@literal rawInputs} - * @param functionResult the result from the function invocation - * @param function the invoked function - * @param executionContext the Azure execution context - * @return the possibly modified function results - */ - protected O postProcessReactiveFunctionResult(I rawInputs, Object functionInputs, Publisher functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext) { - if (FunctionTypeUtils.isMono(function.getOutputType())) { - return postProcessMonoFunctionResult(rawInputs, functionInputs, Mono.from(functionResult), function, - executionContext); - } - return postProcessFluxFunctionResult(rawInputs, functionInputs, Flux.from(functionResult), function, - executionContext); - } - - /** - * Post-processes the {@code Mono} result from a reactive function invocation before returning it to the Azure - * runtime. The default behavior is to {@link Mono#blockOptional()} and {@link #convertOutputIfNecessary possibly - * convert} the result. - * - *

- * Provides a hook for custom function invokers to extend/modify the function results handling. - * - * @param rawInputs the inputs passed in from the Azure runtime - * @param functionInputs the actual inputs used for the function invocation; may be {@link #enhanceInputIfNecessary - * different} from the {@literal rawInputs} - * @param functionResult the Mono result from the function invocation - * @param function the invoked function - * @param executionContext the Azure execution context - * @return the possibly modified function results - */ - @SuppressWarnings("unchecked") - protected O postProcessMonoFunctionResult(I rawInputs, Object functionInputs, Mono functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext) { - return (O) this.convertOutputIfNecessary(rawInputs, functionResult.blockOptional().get()); - } - - /** - * Post-processes the {@code Flux} result from a reactive function invocation before returning it to the Azure - * runtime. The default behavior is to {@link Flux#toIterable() block} and {@link #convertOutputIfNecessary possibly - * convert} the results. - * - *

- * Provides a hook for custom function invokers to extend/modify the function results handling. - * - * @param rawInputs the inputs passed in from the Azure runtime - * @param functionInputs the actual inputs used for the function invocation; may be {@link #enhanceInputIfNecessary - * different} from the {@literal rawInputs} - * @param functionResult the Mono result from the function invocation - * @param function the invoked function - * @param executionContext the Azure execution context - * @return the possibly modified function results - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected O postProcessFluxFunctionResult(I rawInputs, Object functionInputs, Flux functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext) { - List resultList = new ArrayList<>(); - for (Object resultItem : functionResult.toIterable()) { - if (resultItem instanceof Collection) { - resultList.addAll((Collection) resultItem); - } - else { - if (!function.isSupplier() - && Collection.class.isAssignableFrom(FunctionTypeUtils.getRawType(function.getInputType())) - && !Collection.class.isAssignableFrom(FunctionTypeUtils.getRawType(function.getOutputType()))) { - return (O) this.convertOutputIfNecessary(rawInputs, resultItem); - } - else { - resultList.add(resultItem); - } - } - } - return (O) this.convertOutputIfNecessary(rawInputs, resultList); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private void registerFunction(String functionDefinition) { - if (APPLICATION_CONTEXT.containsBean(functionDefinition)) { - FunctionRegistration functionRegistration = new FunctionRegistration( - APPLICATION_CONTEXT.getBean(functionDefinition), functionDefinition); - - Type type = FunctionContextUtils.findType(functionDefinition, APPLICATION_CONTEXT.getBeanFactory()); - - functionRegistration = functionRegistration.type(type); - - ((FunctionRegistry) FUNCTION_CATALOG).register(functionRegistration); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Object enhanceInputIfNecessary(Object input, ExecutionContext executionContext) { - if (input == null) { // Supplier - return input; - } - if (input instanceof Publisher) { - return Flux.from((Publisher) input).map(item -> { - if (item instanceof Message) { - return MessageBuilder.fromMessage((Message) item) - .setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - else { - return constructInputMessageFromItem(input, executionContext); - } - }); - } - else if (input instanceof Message) { - return MessageBuilder.fromMessage((Message) input) - .setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - else if (input instanceof Iterable) { - return Flux.fromIterable((Iterable) input).map(item -> { - return constructInputMessageFromItem(item, executionContext); - }); - } - return constructInputMessageFromItem(input, executionContext); - } - - @SuppressWarnings("unchecked") - private Object convertOutputIfNecessary(Object input, Object output) { - if (input instanceof HttpRequestMessage) { - HttpRequestMessage requestMessage = (HttpRequestMessage) input; - Map headers = null; - if (output instanceof Message) { - headers = ((Message) output).getHeaders(); - output = ((Message) output).getPayload(); - } - Builder responseBuilder = requestMessage.createResponseBuilder(HttpStatus.OK).body(output); - if (headers != null) { - for (Entry headersEntry : headers.entrySet()) { - if (headersEntry.getValue() != null) { - responseBuilder.header(headersEntry.getKey(), headersEntry.getValue().toString()); - } - } - } - return responseBuilder.build(); - } - return output; - } - - @SuppressWarnings("unchecked") - private Message constructInputMessageFromItem(Object input, ExecutionContext executionContext) { - MessageBuilder messageBuilder = null; - if (input instanceof HttpRequestMessage) { - HttpRequestMessage requestMessage = (HttpRequestMessage) input; - Object payload = requestMessage.getHttpMethod() != null - && requestMessage.getHttpMethod().equals(HttpMethod.GET) - ? requestMessage.getQueryParameters() - : requestMessage.getBody(); - - if (payload == null) { - payload = Optional.empty(); - } - messageBuilder = MessageBuilder.withPayload(payload).copyHeaders(this.getHeaders(requestMessage)); - } - else { - messageBuilder = MessageBuilder.withPayload(input); - } - return messageBuilder.setHeaderIfAbsent(EXECUTION_CONTEXT, executionContext).build(); - } - - 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); - } - - private static void initialize(Class configurationClass) { - synchronized (FunctionInvoker.class.getName()) { - if (FUNCTION_CATALOG == null) { - logger.info("Initializing: " + configurationClass); - SpringApplication builder = springApplication(configurationClass); - APPLICATION_CONTEXT = builder.run(); - - Map mf = APPLICATION_CONTEXT.getBeansOfType(FunctionCatalog.class); - if (CollectionUtils.isEmpty(mf)) { - OBJECT_MAPPER = new JacksonMapper(new ObjectMapper()); - JsonMessageConverter jsonConverter = new JsonMessageConverter(OBJECT_MAPPER); - SmartCompositeMessageConverter messageConverter = new SmartCompositeMessageConverter( - Collections.singletonList(jsonConverter)); - FUNCTION_CATALOG = new SimpleFunctionRegistry( - APPLICATION_CONTEXT.getBeanFactory().getConversionService(), - messageConverter, OBJECT_MAPPER); - } - else { - OBJECT_MAPPER = APPLICATION_CONTEXT.getBean(JsonMapper.class); - FUNCTION_CATALOG = mf.values().iterator().next(); - } - } - } - - } - - private static SpringApplication springApplication(Class configurationClass) { - SpringApplication application = new org.springframework.cloud.function.context.FunctionalSpringApplication( - configurationClass); - application.setWebApplicationType(WebApplicationType.NONE); - return application; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvoker.java deleted file mode 100644 index c2af61fb3..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvoker.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021-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 com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage; - - -/** - * 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 Oleg Zhurakousky - * - * @since 3.2 - * - * @deprecated since 4.0.0 in favor of the dependency injection implementation {@link AzureFunctionInstanceInjector}. - * Follow the official documentation for further information. - */ -@Deprecated -public class HttpFunctionInvoker extends - FunctionInvoker, HttpResponseMessage> { - - public HttpFunctionInvoker(Class configurationClass) { - super(configurationClass); - } - - public HttpFunctionInvoker() { - super(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector deleted file mode 100644 index 247910e32..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.adapter.azure.AzureFunctionInstanceInjector \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/spring-azure-function-banner.txt b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/spring-azure-function-banner.txt deleted file mode 100644 index 32225b776..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/resources/spring-azure-function-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - ____ _ _ _____ _ _ - / ___| _ __ _ __(_)_ __ __ _ / \ _____ _ _ __ ___ | ___| _ _ __ ___| |_(_) ___ _ __ ___ - \___ \| '_ \| '__| | '_ \ / _` | / _ \ |_ / | | | '__/ _ \ | |_ | | | | '_ \ / __| __| |/ _ \| '_ \/ __| - ___) | |_) | | | | | | | (_| | / ___ \ / /| |_| | | | __/ | _|| |_| | | | | (__| |_| | (_) | | | \__ \ - |____/| .__/|_| |_|_| |_|\__, | /_/ \_\/___|\__,_|_| \___| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/ - |_| |___/ -${application.title} ${application.version} -Powered by Spring Boot ${spring-boot.version} and Azure Functions \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/CustomFunctionInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/CustomFunctionInvokerTests.java deleted file mode 100644 index 2299007cc..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/CustomFunctionInvokerTests.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2022-2022 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.Arrays; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -import com.microsoft.azure.functions.ExecutionContext; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.function.adapter.azure.helper.TestExecutionContext; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.support.GenericMessage; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.util.Lists.list; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Unit tests for {@link FunctionInvoker} custom result handling. - * - * @author Chris Bono - */ -class CustomFunctionInvokerTests { - - private FunctionInvoker currentInvoker; - - @AfterEach - void closeCurrentInvoker() { - if (this.currentInvoker != null) { - this.currentInvoker.close(); - } - } - - /** - * Verifies custom result handling and proper post-process callback invocation for an imperative function. - */ - @Test - void customImperativeResultHandling() { - FunctionInvoker invoker = new FunctionInvoker(TestFunctionsConfig.class) { - @Override - protected String postProcessImperativeFunctionResult(String rawInputs, Object functionInputs, - Object functionResult, FunctionInvocationWrapper function, ExecutionContext executionContext - ) { - return functionResult + "+imperative"; - } - }; - invoker = spyOnAndCloseAfterTest(invoker); - ExecutionContext executionContext = new TestExecutionContext("imperativeUppercase"); - String result = invoker.handleRequest("foo", executionContext); - assertThat(result).isEqualTo("FOO+imperative"); - - // Below here verifies that the expected callback(s) were invoked w/ the expected arguments - - // Only imperative post-process callback should be called - verify(invoker, never()).postProcessReactiveFunctionResult(anyString(), any(), any(Publisher.class), any(), same(executionContext)); - verify(invoker, never()).postProcessMonoFunctionResult(anyString(), any(), any(Mono.class), any(), same(executionContext)); - verify(invoker, never()).postProcessFluxFunctionResult(anyString(), any(), any(Flux.class), any(), same(executionContext)); - - // Only sniff-test the payload of the input message (the other fields are problematic to verify and no value doing that here) - ArgumentCaptor functionInputsCaptor = ArgumentCaptor.forClass(GenericMessage.class); - verify(invoker).postProcessImperativeFunctionResult(eq("foo"), functionInputsCaptor.capture(), eq("FOO"), any(), same(executionContext)); - assertThat(functionInputsCaptor.getValue()).extracting(GenericMessage::getPayload).isEqualTo("foo"); - } - - /** - * Verifies custom result handling and proper post-process callback invocation for a reactive Mono function. - */ - @Test - void customReactiveMonoResultHandling() { - FunctionInvoker invoker = new FunctionInvoker(TestFunctionsConfig.class) { - @Override - protected String postProcessMonoFunctionResult(String rawInputs, Object functionInputs, Mono functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext - ) { - return functionResult.block().toString() + "+mono"; - } - }; - invoker = spyOnAndCloseAfterTest(invoker); - ExecutionContext executionContext = new TestExecutionContext("reactiveMonoUppercase"); - String result = invoker.handleRequest("foo", executionContext); - assertThat(result).isEqualTo("FOO+mono"); - - // Below here verifies that the expected callback(s) were invoked w/ the expected arguments - - // Only publisher->mono post-process callbacks should be called - verify(invoker, never()).postProcessImperativeFunctionResult(anyString(), any(), any(), any(), same(executionContext)); - verify(invoker, never()).postProcessFluxFunctionResult(anyString(), any(), any(Flux.class), any(), same(executionContext)); - - // Only sniff-test the payload of the input message and the mono (the other fields are problematic to verify and no value doing that here) - ArgumentCaptor functionInputsCaptor = ArgumentCaptor.forClass(GenericMessage.class); - ArgumentCaptor functionResultCaptor = ArgumentCaptor.forClass(Mono.class); - verify(invoker).postProcessReactiveFunctionResult(eq("foo"), functionInputsCaptor.capture(), functionResultCaptor.capture(), any(), same(executionContext)); - verify(invoker).postProcessMonoFunctionResult(eq("foo"), functionInputsCaptor.capture(), functionResultCaptor.capture(), any(), same(executionContext)); - // NOTE: The captors get called twice as the args are just delegated from publisher->mono callback - assertThat(functionInputsCaptor.getAllValues()).extracting(GenericMessage::getPayload).containsExactly("foo", "foo"); - assertThat(functionResultCaptor.getAllValues()).extracting(Mono::block).containsExactly("FOO", "FOO"); - } - - /** - * Verifies custom result handling and proper post-process callback invocation for a reactive Flux function. - */ - @Test - void customReactiveFluxResultHandling() { - FunctionInvoker, String> invoker = new FunctionInvoker, String>(TestFunctionsConfig.class) { - @Override - protected String postProcessFluxFunctionResult(List rawInputs, Object functionInputs, - Flux functionResult, FunctionInvocationWrapper function, ExecutionContext executionContext - ) { - return functionResult.map(o -> o.toString() + "+flux").collectList().block().stream().collect(Collectors.joining("/")); - } - }; - invoker = spyOnAndCloseAfterTest(invoker); - ExecutionContext executionContext = new TestExecutionContext("reactiveFluxUppercase"); - List rawInputs = Arrays.asList("foo", "bar"); - String result = invoker.handleRequest(rawInputs, executionContext); - assertThat(result).isEqualTo("FOO+flux/BAR+flux"); - - // Below here verifies that the expected callback(s) were invoked w/ the expected arguments - - // Only publisher->flux post-process callbacks should be called - verify(invoker, never()).postProcessImperativeFunctionResult(anyList(), any(), any(), any(), same(executionContext)); - verify(invoker, never()).postProcessMonoFunctionResult(anyList(), any(), any(Mono.class), any(), same(executionContext)); - - // Only sniff-test the payload of the input message and the mono (the other fields are problematic to verify and no value doing that here) - ArgumentCaptor> functionInputsCaptor = ArgumentCaptor.forClass(Flux.class); - ArgumentCaptor functionResultCaptor = ArgumentCaptor.forClass(Flux.class); - verify(invoker).postProcessReactiveFunctionResult(same(rawInputs), functionInputsCaptor.capture(), functionResultCaptor.capture(), any(), same(executionContext)); - verify(invoker).postProcessFluxFunctionResult(same(rawInputs), functionInputsCaptor.capture(), functionResultCaptor.capture(), any(), same(executionContext)); - - // NOTE: The captors get called twice as the args are just delegated from publisher->flux callback - - // The functionInputs for each call is Flux with 2 items - one for 'foo' and one for 'bar' - assertThat(functionInputsCaptor.getAllValues()) - .extracting(Flux::collectList).extracting(Mono::block) - .flatExtracting(fluxAsList -> fluxAsList.stream().collect(Collectors.toList())) - .extracting(GenericMessage::getPayload).containsExactlyInAnyOrder("foo", "bar", "foo", "bar"); - - // The functionResult for each call is a Flux w/ 2 items { "FOO", "BAR" } - assertThat(functionResultCaptor.getAllValues()) - .extracting(Flux::collectList).extracting(Mono::block) - .containsExactlyInAnyOrder(list("FOO", "BAR"), list("FOO", "BAR")); - } - - private FunctionInvoker spyOnAndCloseAfterTest(FunctionInvoker invoker) { - this.currentInvoker = invoker; - return spy(invoker); - } - - @Configuration - @EnableAutoConfiguration - static class TestFunctionsConfig { - - @Bean - public Function imperativeUppercase() { - return (s) -> s.toUpperCase(); - } - - @Bean - public Function, Mono> reactiveMonoUppercase() { - return (m) -> m.map(String::toUpperCase); - } - - @Bean - public Function, Flux> reactiveFluxUppercase() { - return (f) -> f.map(String::toUpperCase); - } - - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/FunctionInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/FunctionInvokerTests.java deleted file mode 100644 index a010af1d0..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/FunctionInvokerTests.java +++ /dev/null @@ -1,369 +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.azure; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import com.microsoft.azure.functions.ExecutionContext; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.function.adapter.azure.helper.TestExecutionContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class FunctionInvokerTests { - - private FunctionInvoker handler = null; - - FunctionInvoker handler(Class config) { - FunctionInvoker handler = new FunctionInvoker( - config); - this.handler = handler; - return handler; - } - -// @Test // this is wrong too since function is Flux, Flux and while input may be single value, the output can still be multiple - public void bareConfig() { - FunctionInvoker handler = handler(BareConfig.class); - Bar bar = handler.handleRequest(new Foo("bar"), - new TestExecutionContext("uppercase")); - assertThat(bar.getValue()).isEqualTo("BAR"); - } - - @Test - public void autoConfig() { - FunctionInvoker handler = handler(AutoConfig.class); - Bar bar = handler.handleRequest(new Foo("bar"), - new TestExecutionContext("uppercase")); - assertThat(bar.getValue()).isEqualTo("BAR"); - } - - @Test - public void multiConfig() { - FunctionInvoker handler = handler(MultiConfig.class); - Bar bar = handler.handleRequest(new Foo("bar"), - new TestExecutionContext("uppercase")); - assertThat(bar.getValue()).isEqualTo("BAR"); - } - - @Test - public void implicitListConfig() { - FunctionInvoker, List> handler = handler( - AutoConfig.class); - List bar = handler.handleRequest(Arrays.asList(new Foo("bar"), new Foo("baz")), - new TestExecutionContext("uppercase")); - assertThat(bar).hasSize(2); - assertThat(bar.get(0).getValue()).isEqualTo("BAR"); - assertThat(bar.get(1).getValue()).isEqualTo("BAZ"); - } - - @Test - public void listToListConfig() { - FunctionInvoker, List> handler = handler( - ListConfig.class); - List bar = handler.handleRequest( - Arrays.asList(new Foo("bar"), new Foo("baz")), - new TestExecutionContext("uppercase")); - assertThat(bar).hasSize(2); - assertThat(bar.get(0).getValue()).isEqualTo("BAR"); - } - - @Test - public void listToListSingleConfig() { - FunctionInvoker, List> handler = handler( - ListConfig.class); - List bar = handler.handleRequest(Arrays.asList(new Foo("bar")), - new TestExecutionContext("uppercase")); - assertThat(bar).hasSize(1); - assertThat(bar.get(0).getValue()).isEqualTo("BAR"); - } - - @Test - public void collectConfig() { - FunctionInvoker, Bar> handler = handler( - CollectConfig.class); - Bar bar = handler.handleRequest(Arrays.asList(new Foo("bar")), - new TestExecutionContext("uppercase")); - assertThat(bar.getValue()).isEqualTo("BAR"); - } - - @Test - public void functionNonFluxBean() { - FunctionInvoker handler = handler(NonFluxFunctionConfig.class); - Bar bar = handler.handleRequest(new Foo("bar"), new TestExecutionContext("function")); - assertThat(bar).isNotNull(); - } - - @Test - public void supplierNonFluxBean() { - FunctionInvoker> handler = handler(NonFluxSupplierConfig.class); - List result = handler.handleRequest(new TestExecutionContext("supplier")); - - assertThat(result).isNotEmpty(); - assertThat(result.toString()).isEqualTo("[foo1, foo2]"); - } - - @Test - public void supplierPublisherBean() { - FunctionInvoker handler = handler(ReactiveSupplierConfig.class); - Foo resultSingle = (Foo) handler.handleRequest(new TestExecutionContext("suppliermono")); - assertThat(resultSingle.getValue()).isEqualTo("hello"); - - List resultList = (List) handler.handleRequest(new TestExecutionContext("supplierflux")); - assertThat(resultList.size()).isEqualTo(2); - } - - private static String consumerResult; - - @Test - public void consumerNonFluxBean() { - FunctionInvoker handler = handler(NonFluxConsumerConfig.class); - Object result = handler.handleRequest("foo1", new TestExecutionContext("consumer")); - - assertThat(result).isNull(); - assertThat(consumerResult).isEqualTo("foo1"); - } - - @Test - public void testReactiveFunctions() { - FunctionInvoker handler = handler(ReactiveFunctionConfiguration.class); - String result = handler.handleRequest("hello", new TestExecutionContext("uppercaseMono")); - - System.out.println(result); - -// assertThat(result).isNull(); -// assertThat(consumerResult).isEqualTo("foo1"); - } - - @AfterEach - public void close() throws IOException { - if (this.handler != null) { - this.handler.close(); - } - } - - @Configuration - protected static class NonFluxFunctionConfig { - - @Bean - public Function function() { - return foo -> new Bar(); - } - - } - - @Configuration - @EnableAutoConfiguration - protected static class ReactiveFunctionConfiguration { - - @Bean - public Function, Flux> echoStream() { - return f -> f; - } - - @Bean - public Function, Mono> uppercaseMono() { - return f -> f.map(v -> v.toUpperCase()); - } - - } - - @Configuration - protected static class NonFluxSupplierConfig { - - @Bean - public Supplier> supplier() { - return () -> Arrays.asList("foo1", "foo2"); - } - - } - - @Configuration - protected static class NonFluxConsumerConfig { - - @Bean - public Consumer consumer() { - return (v) -> consumerResult = v; - } - - } - - @Configuration -// @EnableAutoConfiguration - protected static class ReactiveSupplierConfig { - - @Bean - public Supplier> suppliermono() { - return () -> Mono.just(new Foo("hello")); - } - - @Bean - public Supplier> supplierflux() { - return () -> Flux.just(new Foo("hello"), new Foo("bye")); - } - - } - - @Configuration - protected static class BareConfig { - - @Bean("uppercase") - public Function, Flux> function() { - return foos -> foos.map(foo -> new Bar(foo.getValue().toUpperCase())); - } - - } - - @Configuration - @EnableAutoConfiguration - protected static class AutoConfig { - - @Bean - public Function, Bar> uppercase() { - return message -> { - Foo foo = message.getPayload(); - ExecutionContext targetContext = (ExecutionContext) message.getHeaders().get("executionContext"); - targetContext.getLogger().info("Invoking 'uppercase' on " + foo.getValue()); - return new Bar(foo.getValue().toUpperCase()); - }; - } - - } - - @Configuration - @EnableAutoConfiguration - protected static class ListConfig { - - @Bean - public Function, List> uppercase() { - return foos -> { - List bars = foos.stream().map(foo -> new Bar(foo.getValue().toUpperCase())) - .collect(Collectors.toList()); - return bars; - }; - } - - } - - @Configuration - @EnableAutoConfiguration - protected static class CollectConfig { - - @Bean - public Function, Bar> uppercase() { - return foos -> new Bar(foos.stream().map(foo -> foo.getValue().toUpperCase()) - .collect(Collectors.joining(","))); - } - - } - - @Configuration - @EnableAutoConfiguration - protected static class MultiConfig { - - @Bean - public Function, Bar> uppercase() { - - return message -> { - ExecutionContext context = (ExecutionContext) message.getHeaders().get("executionContext"); - Foo foo = message.getPayload(); - context.getLogger().info("Executing uppercase function"); - return new Bar(foo.getValue().toUpperCase()); - }; - } - - @Bean - public Function, Foo> lowercase() { - return message -> { - ExecutionContext context = (ExecutionContext) message.getHeaders().get("executionContext"); - Bar bar = message.getPayload(); - context.getLogger().info("Executing lowercase function"); - return new Foo(bar.getValue().toLowerCase()); - }; - } - - } - -} - -class Foo { - - private String value; - - Foo() { - } - - Foo(String value) { - this.value = value; - } - - public String lowercase() { - return this.value.toLowerCase(); - } - - public String uppercase() { - return this.value.toUpperCase(); - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - -} - -class Bar { - - private String value; - - Bar() { - } - - 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/src/test/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvokerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvokerTests.java deleted file mode 100644 index 20445fdc4..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/HttpFunctionInvokerTests.java +++ /dev/null @@ -1,160 +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.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpResponseMessage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.function.adapter.azure.helper.HttpRequestMessageStub; -import org.springframework.cloud.function.adapter.azure.helper.TestExecutionContext; -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 Markus Gulden - */ -public class HttpFunctionInvokerTests { - - private HttpFunctionInvoker handler = null; - - HttpFunctionInvoker handler(Class config) { - HttpFunctionInvoker handler = new HttpFunctionInvoker( - config); - this.handler = handler; - return handler; - } - - @Test - public void testWithBody() { - HttpFunctionInvoker handler = handler( - FunctionMessageBodyConfig.class); - HttpRequestMessageStub request = new HttpRequestMessageStub(); - request.setBody(new Foo("foo")); - - HttpResponseMessage response = handler.handleRequest(request, - new TestExecutionContext("uppercase")); - - assertThat(response.getBody()).isInstanceOf(Bar.class); - assertThat(response.getStatusCode()).isEqualTo(200); - Bar body = (Bar) response.getBody(); - assertThat(body.getValue()).isEqualTo("FOO"); - } - - @Test - public void testWithRequestParameters() throws URISyntaxException { - HttpFunctionInvoker handler = handler( - FunctionMessageEchoReqParametersConfig.class); - HttpRequestMessageStub request = new HttpRequestMessageStub(); - request.setUri(new URI("http://localhost:8080/pathValue")); - request.setHeaders(Collections.singletonMap("test-header", "headerValue")); - request.setQueryParameters(Collections.singletonMap("query", "queryValue")); - request.setHttpMethod(HttpMethod.GET); - - HttpResponseMessage response = handler.handleRequest(request, - new TestExecutionContext("uppercase")); - - assertThat(response.getStatusCode()).isEqualTo(200); - assertThat(response.getHeader("path")).isEqualTo("/pathValue"); - assertThat(response.getHeader("query")).isEqualTo("queryValue"); - assertThat(response.getHeader("test-header")).isEqualTo("headerValue"); - Bar body = (Bar) response.getBody(); - assertThat(body.getValue()).isEqualTo("body"); - } - - @Test - public void testWithEmptyBody() { - HttpFunctionInvoker handler = handler( - FunctionMessageConsumerConfig.class); - HttpRequestMessageStub request = new HttpRequestMessageStub(); - - HttpResponseMessage response = handler.handleRequest(request, - new TestExecutionContext("uppercase")); - - assertThat(response.getStatusCode()).isEqualTo(200); - Bar body = (Bar) response.getBody(); - assertThat(body).isNull(); - } - - @AfterEach - public void close() throws IOException { - if (this.handler != null) { - this.handler.close(); - } - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class FunctionMessageBodyConfig { - - @Bean - public Function, Message> function() { - return (foo -> { - Map headers = new HashMap<>(); - return new GenericMessage<>( - new Bar(foo.getPayload().getValue().toUpperCase()), headers); - }); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.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 }) - protected static class FunctionMessageConsumerConfig { - - @Bean - public Consumer> function() { - return (foo -> { - }); - } - - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/BuilderStub.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/BuilderStub.java deleted file mode 100644 index 94cd39f6d..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/BuilderStub.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2023-2023 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.helper; - -import java.util.HashMap; -import java.util.Map; - -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; -import com.microsoft.azure.functions.HttpStatusType; - -public class BuilderStub implements Builder { - - private HttpStatusType status; - private Map headers = new HashMap<>(); - private Object body; - - @Override - public Builder status(HttpStatusType status) { - this.status = status; - return this; - } - - @Override - public Builder header(String key, String value) { - headers.put(key, value); - return this; - } - - @Override - public Builder body(Object body) { - this.body = body; - return this; - } - - @Override - public HttpResponseMessage build() { - return new HttpResponseMessageStub(this.status, this.headers, this.body); - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpRequestMessageStub.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpRequestMessageStub.java deleted file mode 100644 index b7db2b7d1..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpRequestMessageStub.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2023-2023 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.helper; - -import java.net.URI; -import java.util.Map; - -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpResponseMessage.Builder; -import com.microsoft.azure.functions.HttpStatus; -import com.microsoft.azure.functions.HttpStatusType; - -public class HttpRequestMessageStub implements HttpRequestMessage { - - private URI uri; - private HttpMethod httpMethod; - private Map headers; - private Map queryParameters; - private I body; - - public void setUri(URI uri) { - this.uri = uri; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public void setQueryParameters(Map queryParameters) { - this.queryParameters = queryParameters; - } - - public void setBody(I body) { - this.body = body; - } - - @Override - public URI getUri() { - return this.uri; - } - - @Override - public HttpMethod getHttpMethod() { - return this.httpMethod; - } - - @Override - public Map getHeaders() { - return this.headers; - } - - @Override - public Map getQueryParameters() { - return this.queryParameters; - } - - @Override - public I getBody() { - return this.body; - } - - @Override - public HttpResponseMessage.Builder createResponseBuilder(HttpStatusType status) { - return new BuilderStub().status(status); - } - - @Override - public Builder createResponseBuilder(HttpStatus status) { - return new BuilderStub().status(status); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpResponseMessageStub.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpResponseMessageStub.java deleted file mode 100644 index ffd939071..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/HttpResponseMessageStub.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023-2023 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.helper; - -import java.util.HashMap; -import java.util.Map; - -import com.microsoft.azure.functions.HttpResponseMessage; -import com.microsoft.azure.functions.HttpStatusType; - -public class HttpResponseMessageStub implements HttpResponseMessage { - - private HttpStatusType status; - private Map headers = new HashMap<>(); - private Object body; - - public HttpResponseMessageStub(HttpStatusType status, Map headers, - Object body) { - this.status = status; - this.headers = headers; - this.body = body; - } - - @Override - public HttpStatusType getStatus() { - return this.status; - } - - @Override - public String getHeader(String key) { - return this.headers.get(key); - } - - @Override - public Object getBody() { - return this.body; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/TestExecutionContext.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/TestExecutionContext.java deleted file mode 100644 index e7cb7934a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/helper/TestExecutionContext.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.adapter.azure.helper; - -import java.util.UUID; -import java.util.logging.Logger; - -import com.microsoft.azure.functions.ExecutionContext; - -public class TestExecutionContext implements ExecutionContext { - - private String name; - - public TestExecutionContext(String name) { - this.name = name; - } - - @Override - public Logger getLogger() { - return Logger.getLogger(TestExecutionContext.class.getName()); - } - - @Override - public String getInvocationId() { - return UUID.randomUUID().toString(); - } - - @Override - public String getFunctionName() { - return this.name; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/AzureFunctionInstanceInjectorTest.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/AzureFunctionInstanceInjectorTest.java deleted file mode 100644 index 7a52dee43..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/AzureFunctionInstanceInjectorTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2022-2022 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.injector; - -import java.util.Optional; -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; -import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.adapter.azure.AzureFunctionInstanceInjector; -import org.springframework.cloud.function.adapter.azure.AzureFunctionUtil; -import org.springframework.cloud.function.adapter.azure.helper.HttpRequestMessageStub; -import org.springframework.cloud.function.adapter.azure.helper.TestExecutionContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.stereotype.Component; - -/** - * This is an example JUnit test for Azure Adapter. - * - * @author Christian Tzolov - */ -public class AzureFunctionInstanceInjectorTest { - - static ExecutionContext TEST_EXECUTION_CONTEXT = new TestExecutionContext("hello"); - - @Test - public void testFunctionInjector() throws Exception { - - // The SpringBootApplication class - System.setProperty("MAIN_CLASS", MySpringConfig.class.getName()); - - FunctionInstanceInjector injector = new AzureFunctionInstanceInjector(); - - // Emulates the Azure Function Java Runtime DI call - MyAzureFunction azureFunction = injector.getInstance(MyAzureFunction.class); - - Assertions.assertThat(azureFunction).isNotNull(); - - HttpRequestMessageStub> requestStub = new HttpRequestMessageStub>(); - - requestStub.setBody(Optional.of("payload")); - - String result = azureFunction.execute(requestStub, TEST_EXECUTION_CONTEXT); - - Assertions.assertThat(result).isEqualTo("PAYLOAD"); - - Assertions.assertThat(azureFunction).isInstanceOf(MyAzureFunction.class); - } - - @Component - public static class MyAzureFunction { - - @Autowired - private Function, String> uppercase; - - @FunctionName("hello") - public String execute( - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - Message enhancedRequest = (Message) AzureFunctionUtil.enhanceInputIfNecessary( - request.getBody().get(), - context); - - return uppercase.apply(enhancedRequest); - } - } - - @Configuration - @ComponentScan - public static class MySpringConfig { - - @Bean - public Function, String> uppercaseBean() { - return message -> { - ExecutionContext context = (ExecutionContext) message.getHeaders() - .get(AzureFunctionUtil.EXECUTION_CONTEXT); - - Assertions.assertThat(context).isNotNull(); - Assertions.assertThat(context.getFunctionName()).isEqualTo("hello"); - - return message.getPayload().toUpperCase(); - }; - - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/FunctionInstanceInjectorServiceLoadingTest.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/FunctionInstanceInjectorServiceLoadingTest.java deleted file mode 100644 index 0af13fcd7..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/injector/FunctionInstanceInjectorServiceLoadingTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2022-2022 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.injector; - -import java.util.Iterator; -import java.util.Optional; -import java.util.ServiceLoader; -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; -import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter; -import org.springframework.cloud.function.adapter.azure.AzureFunctionInstanceInjector; -import org.springframework.cloud.function.adapter.azure.AzureFunctionUtil; -import org.springframework.cloud.function.adapter.azure.helper.HttpRequestMessageStub; -import org.springframework.cloud.function.adapter.azure.helper.TestExecutionContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.ComponentScan.Filter; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; -import org.springframework.messaging.Message; -import org.springframework.stereotype.Component; - -/** - * @author Christian Tzolov - */ -public class FunctionInstanceInjectorServiceLoadingTest { - - static ExecutionContext executionContext = new TestExecutionContext("hello"); - - @Test - public void testFunctionInjector() throws Exception { - - FunctionInstanceInjector injector = initializeFunctionInstanceInjector(); - Assertions.assertThat(injector).isNotNull(); - Assertions.assertThat(injector).isInstanceOf(AzureFunctionInstanceInjector.class); - - System.setProperty("MAIN_CLASS", MyMainConfig.class.getName()); - - MyAzureTestFunction functionInstance = injector.getInstance(MyAzureTestFunction.class); - - HttpRequestMessageStub> request = new HttpRequestMessageStub>(); - - request.setBody(Optional.of("test")); - - String result = functionInstance.execute(request, executionContext); - - Assertions.assertThat(result).isEqualTo("TEST"); - - Assertions.assertThat(functionInstance).isNotNull(); - Assertions.assertThat(functionInstance).isInstanceOf(MyAzureTestFunction.class); - } - - private static FunctionInstanceInjector initializeFunctionInstanceInjector() { - FunctionInstanceInjector functionInstanceInjector = null; - ClassLoader prevContextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Iterator iterator = ServiceLoader.load(FunctionInstanceInjector.class).iterator(); - if (iterator.hasNext()) { - functionInstanceInjector = iterator.next(); - if (iterator.hasNext()) { - throw new RuntimeException( - "Customer function app has multiple FunctionInstanceInjector implementations"); - } - } - else { - throw new IllegalStateException("Failed to resolve the AzureFunctionInstanceInjector as java service!"); - } - } - finally { - Thread.currentThread().setContextClassLoader(prevContextClassLoader); - } - return functionInstanceInjector; - } - - @Configuration - @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)}) - public static class MyMainConfig { - - @Bean - public Function, String> uppercase() { - return message -> { - ExecutionContext context = (ExecutionContext) message.getHeaders() - .get(AzureFunctionUtil.EXECUTION_CONTEXT); - Assertions.assertThat(context).isNotNull(); - Assertions.assertThat(context.getFunctionName()).isEqualTo("hello"); - return message.getPayload().toUpperCase(); - }; - } - } - - @Component - public static class MyAzureTestFunction { - - @Autowired - private Function, String> uppercase; - - @FunctionName("ditest") - public String execute( - @HttpTrigger(name = "req", methods = { HttpMethod.GET, - HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - Message enhancedRequest = (Message) AzureFunctionUtil.enhanceInputIfNecessary( - request.getBody().get(), - context); - return uppercase.apply(enhancedRequest); - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/resources/log4j.xml b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/resources/log4j.xml deleted file mode 100644 index 55fad21dc..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/resources/log4j.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file 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 deleted file mode 100644 index d16fe0ff8..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-adapter-gcp - Spring Cloud Function Adapter GCP - Spring Cloud Function Adapter for Google Cloud Functions - - - spring-cloud-function-adapter-parent - org.springframework.cloud - 4.1.0-SNAPSHOT - - - - UTF-8 - UTF-8 - 1.0.3 - 1.0.3 - - - - - com.google.cloud.functions - functions-framework-api - ${google.cloud.functions.api.version} - - - com.google.code.gson - gson - - - org.springframework.cloud - spring-cloud-function-context - - - - - org.springframework.boot - spring-boot-loader-tools - - - org.springframework.boot - spring-boot-loader - - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework - spring-web - test - - - com.google.cloud.functions.invoker - java-function-invoker - ${google.cloud.functions.invoker.version} - test - - - - com.github.blindpirate - junit5-capture-system-output-extension - 0.1.2 - test - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/FunctionInvoker.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/FunctionInvoker.java deleted file mode 100644 index 062787d84..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/FunctionInvoker.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2020-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.gcp; - -import java.io.BufferedReader; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Map.Entry; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import com.google.cloud.functions.Context; -import com.google.cloud.functions.HttpFunction; -import com.google.cloud.functions.HttpRequest; -import com.google.cloud.functions.HttpResponse; -import com.google.cloud.functions.RawBackgroundFunction; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.WebApplicationType; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionalSpringApplication; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.utils.FunctionClassUtils; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.util.MimeTypeUtils; - -/** - * Implementation of {@link HttpFunction} and {@link RawBackgroundFunction} for Google - * Cloud Function (GCF). This is the Spring Cloud Function adapter for GCF HTTP and Raw - * Background function. - * - * @author Dmitry Solomakha - * @author Mike Eltsufin - * @author Oleg Zhurakousky - * @author Biju Kunjummen - * @since 3.0.4 - */ -public class FunctionInvoker implements HttpFunction, RawBackgroundFunction { - - private static final Log log = LogFactory.getLog(FunctionInvoker.class); - - /** - * Constant specifying Http Status Code. Accessible to users by calling 'FunctionInvoker.HTTP_STATUS_CODE' - */ - public static final String HTTP_STATUS_CODE = "statusCode"; - - private String functionName = ""; - - protected FunctionCatalog catalog; - - private FunctionInvocationWrapper functionWrapped; - - private ConfigurableApplicationContext context; - - public FunctionInvoker() { - this(FunctionClassUtils.getStartClass()); - } - - public FunctionInvoker(Class configurationClass) { - init(configurationClass); - } - - private void init(Class configurationClass) { - // Default to GSON if implementation not specified. - if (!System.getenv().containsKey(ContextFunctionCatalogAutoConfiguration.JSON_MAPPER_PROPERTY)) { - System.setProperty(ContextFunctionCatalogAutoConfiguration.JSON_MAPPER_PROPERTY, "gson"); - } - Thread.currentThread() // TODO: remove after upgrading to 1.0.0-alpha-2-rc5 - .setContextClassLoader(FunctionInvoker.class.getClassLoader()); - - log.info("Initializing: " + configurationClass); - SpringApplication springApplication = springApplication(configurationClass); - this.context = springApplication.run(); - this.catalog = this.context.getBean(FunctionCatalog.class); - initFunctionConsumerOrSupplierFromCatalog(); - } - - private Function, Message> lookupFunction() { - Function, Message> function = this.catalog.lookup(functionName, - MimeTypeUtils.APPLICATION_JSON.toString()); - Assert.notNull(function, "'function' with name '" + functionName + "' must not be null"); - return function; - } - - /** - * The implementation of a GCF {@link HttpFunction} that will be used as the entry - * point from GCF. - */ - @Override - public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { - Function, Message> function = lookupFunction(); - - Message message = this.functionWrapped.getInputType() == Void.class || this.functionWrapped.getInputType() == null ? null - : MessageBuilder.withPayload(httpRequest.getReader()).copyHeaders(httpRequest.getHeaders()).build(); - - Message result = function.apply(message); - - if (result != null) { - MessageHeaders headers = result.getHeaders(); - httpResponse.setContentType(result.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString()); - httpResponse.getWriter().write(new String(result.getPayload(), StandardCharsets.UTF_8)); - for (Entry header : headers.entrySet()) { - Object values = header.getValue(); - if (values instanceof Collection) { - String headerValue = ((Collection) values).stream().map(item -> item.toString()).collect(Collectors.joining(",")); - httpResponse.appendHeader(header.getKey(), headerValue); - } - else { - httpResponse.appendHeader(header.getKey(), header.getValue().toString()); - } - } - httpRequest.getContentType().ifPresent(contentType -> httpResponse.setContentType(contentType)); - - if (headers.containsKey(HTTP_STATUS_CODE)) { - if (headers.get(HTTP_STATUS_CODE) instanceof Integer) { - httpResponse.setStatusCode((int) headers.get(HTTP_STATUS_CODE)); - } - else { - log.warn("The statusCode should be an Integer value"); - } - } - } - } - - /** - * The implementation of a GCF {@link RawBackgroundFunction} that will be used as the - * entry point from GCF. - * - * @param json the payload. - * @param context event context. - * @since 3.0.5 - */ - @Override - public void accept(String json, Context context) { - Function, Message> function = lookupFunction(); - Message message = this.functionWrapped.getInputType() == Void.class ? null - : MessageBuilder.withPayload(json).setHeader("gcf_context", context).build(); - - Message result = function.apply(message); - - if (result != null) { - log.info("Dropping background function result: " + new String(result.getPayload())); - } - } - - private void initFunctionConsumerOrSupplierFromCatalog() { - String name = resolveName(Function.class); - this.functionWrapped = this.catalog.lookup(Function.class, name); - if (this.functionWrapped != null) { - this.functionName = name; - return; - } - name = resolveName(Consumer.class); - this.functionWrapped = this.catalog.lookup(Consumer.class, name); - if (this.functionWrapped != null) { - this.functionName = name; - return; - } - - name = resolveName(Supplier.class); - this.functionWrapped = this.catalog.lookup(Supplier.class, name); - if (this.functionWrapped != null) { - this.functionName = name; - return; - } - - // Default to Routing Function - this.functionWrapped = this.catalog.lookup(RoutingFunction.FUNCTION_NAME, "application/json"); - if (this.functionWrapped != null) { - this.functionName = RoutingFunction.FUNCTION_NAME; - } - - Assert.notNull(this.functionWrapped, "Couldn't resolve a handler function"); - } - - private String resolveName(Class type) { - if (System.getenv().containsKey("spring.cloud.function.definition")) { - return System.getenv("spring.cloud.function.definition"); - } - String functionName = this.context.getEnvironment().getProperty("function.name"); - if (functionName != null) { - return functionName; - } - else if (type.isAssignableFrom(Function.class)) { - return "function"; - } - else if (type.isAssignableFrom(Consumer.class)) { - return "consumer"; - } - else if (type.isAssignableFrom(Supplier.class)) { - return "supplier"; - } - throw new IllegalStateException("Unknown type " + type); - } - - private SpringApplication springApplication(Class configurationClass) { - SpringApplication application = new FunctionalSpringApplication(configurationClass); - application.setWebApplicationType(WebApplicationType.NONE); - return application; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/GcfJarLauncher.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/GcfJarLauncher.java deleted file mode 100644 index f45839ab5..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/GcfJarLauncher.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018-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.gcp; - -import com.google.cloud.functions.Context; -import com.google.cloud.functions.HttpFunction; -import com.google.cloud.functions.HttpRequest; -import com.google.cloud.functions.HttpResponse; -import com.google.cloud.functions.RawBackgroundFunction; - -import org.springframework.boot.loader.JarLauncher; -import org.springframework.boot.loader.jar.JarFile; - -/** - * The launcher class written at the top-level of the output JAR to be deployed to - * Google Cloud Functions. This is the entry point to the function when run from JAR. - * - * @author Ray Tsang - * @author Daniel Zou - */ -public class GcfJarLauncher extends JarLauncher implements HttpFunction, RawBackgroundFunction { - - private final ClassLoader loader; - - private final Object delegate; - - public GcfJarLauncher() throws Exception { - JarFile.registerUrlProtocolHandler(); - - this.loader = createClassLoader(getClassPathArchivesIterator()); - - Class clazz = this.loader - .loadClass("org.springframework.cloud.function.adapter.gcp.FunctionInvoker"); - this.delegate = clazz.getConstructor().newInstance(); - } - @Override - public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { - Thread.currentThread().setContextClassLoader(this.loader); - ((HttpFunction) delegate).service(httpRequest, httpResponse); - } - - @Override - public void accept(String json, Context context) throws Exception { - Thread.currentThread().setContextClassLoader(this.loader); - ((RawBackgroundFunction) delegate).accept(json, context); - } -} - diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayout.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayout.java deleted file mode 100644 index 874e0c66a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayout.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018-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.gcp.layout; - -import java.io.IOException; - -import org.springframework.boot.loader.tools.CustomLoaderLayout; -import org.springframework.boot.loader.tools.Layouts; -import org.springframework.boot.loader.tools.LoaderClassesWriter; -import org.springframework.cloud.function.adapter.gcp.GcfJarLauncher; - -/** - * A custom JAR Layout that writes GCF adapter classes to the top-level of the output JAR - * for deploying to GCF. - * - * @author Ray Tsang - * @author Daniel Zou - */ -public class GcfJarLayout extends Layouts.Jar implements CustomLoaderLayout { - - private static final String LAUNCHER_NAME = GcfJarLauncher.class.getCanonicalName(); - - @Override - public String getLauncherClassName() { - return LAUNCHER_NAME; - } - - @Override - public boolean isExecutable() { - return false; - } - - @Override - public void writeLoadedClasses(LoaderClassesWriter writer) throws IOException { - writer.writeLoaderClasses(); - - String jarName = LAUNCHER_NAME.replaceAll("\\.", "/") + ".class"; - writer.writeEntry( - jarName, GcfJarLauncher.class.getResourceAsStream("/" + jarName)); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayoutFactory.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayoutFactory.java deleted file mode 100644 index 87eacef00..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/java/org/springframework/cloud/function/adapter/gcp/layout/GcfJarLayoutFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2018-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.gcp.layout; - -import java.io.File; - -import org.springframework.boot.loader.tools.Layout; -import org.springframework.boot.loader.tools.LayoutFactory; - -/** - * Factory boilerplate class that constructs {@link GcfJarLayout}. - * - * @author Ray Tsang - * @author Daniel Zou - */ -public class GcfJarLayoutFactory implements LayoutFactory { - - @Override - public Layout getLayout(File source) { - return new GcfJarLayout(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/resources/META-INF/spring.factories b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 76392ffda..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.loader.tools.LayoutFactory=\ -org.springframework.cloud.function.adapter.gcp.layout.GcfJarLayoutFactory diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/Context.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/Context.java deleted file mode 100644 index 46e77e425..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/Context.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020-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.gcp; - -/** - * An immutable implementation of the Google Cloud Function - * {@link com.google.cloud.functions.Context} interface. - * - * @author Mike Eltsufin - * @since 3.0.5 - */ -public class Context implements com.google.cloud.functions.Context { - - private String eventId; - - private String timestamp; - - private String eventType; - - private String resource; - - public Context() { - } - - public Context(String eventId, String timestamp, String eventType, String resource) { - this.eventId = eventId; - this.timestamp = timestamp; - this.eventType = eventType; - this.resource = resource; - } - - @Override - public String eventId() { - return this.eventId; - - } - - @Override - public String timestamp() { - return this.timestamp; - - } - - @Override - public String eventType() { - return this.eventType; - - } - - @Override - public String resource() { - return this.resource; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerBackgroundTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerBackgroundTests.java deleted file mode 100644 index 29951e594..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerBackgroundTests.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2020-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.gcp; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.github.blindpirate.extensions.CaptureSystemOutput; -import com.google.gson.Gson; -import org.hamcrest.Matchers; -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.cloud.function.json.JsonMapper; -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.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.MessageBuilder; - -/** - * Unit tests for the background functions adapter for Google Cloud Functions. - * - * @author Dmitry Solomakha - * @author Mike Eltsufin - */ -@CaptureSystemOutput -public class FunctionInvokerBackgroundTests { - - private static final Gson gson = new Gson(); - - private static final String DROPPED_LOG_PREFIX = "Dropping background function result: "; - - @Test - public void testHelloWorldSupplier_Background(CaptureSystemOutput.OutputCapture outputCapture) { - testBackgroundFunction(outputCapture, HelloWorldSupplier.class, null, "Hello World!", null, null); - } - @Test - public void testJsonInputFunction_Background(CaptureSystemOutput.OutputCapture outputCapture) { - testBackgroundFunction(outputCapture, JsonInputFunction.class, new IncomingRequest("hello"), - "Thank you for sending the message: hello", null, null); - } - - @Test - public void testJsonInputOutputFunction_Background(CaptureSystemOutput.OutputCapture outputCapture) { - testBackgroundFunction(outputCapture, JsonInputOutputFunction.class, new IncomingRequest("hello"), - new OutgoingResponse("Thank you for sending the message: hello"), null, null); - } - - @Test - public void testJsonInputConsumer(CaptureSystemOutput.OutputCapture outputCapture) { - testBackgroundFunction(outputCapture, JsonInputConsumer.class, new IncomingRequest("hello"), null, - "Thank you for sending the message: hello", null); - } - - @Test - public void testPubSubBackgroundFunction_PubSub(CaptureSystemOutput.OutputCapture outputCapture) { - PubSubMessage pubSubMessage = new PubSubMessage(); - pubSubMessage.setData("hello"); - testBackgroundFunction(outputCapture, PubsubBackgroundFunction.class, pubSubMessage, null, - "Thank you for sending the message: hello", "google.pubsub.topic.publish"); - } - - @Test - public void testPubSubBackgroundFunction_PubSubPayload(CaptureSystemOutput.OutputCapture outputCapture) { - PubSubMessage pubSubMessage = new PubSubMessage(); - IncomingRequest message = new IncomingRequest("Hello"); - pubSubMessage.setData(gson.toJson(message)); - testBackgroundFunction(outputCapture, PubsubBackgroundFunctionPayload.class, pubSubMessage, null, - "Thank you for sending the message: Hello", "google.pubsub.topic.publish"); - } - - @Test - public void testPubSubBackgroundFunction_StringMessage(CaptureSystemOutput.OutputCapture outputCapture) { - PubSubMessage pubSubMessage = new PubSubMessage(); - pubSubMessage.setMessageId("1234"); - pubSubMessage.setData("Hello"); - testBackgroundFunction(outputCapture, PubsubBackgroundFunctionStringMessage.class, pubSubMessage, null, - "Message: Hello; Type: google.pubsub.topic.publish; Message ID: 1234", "google.pubsub.topic.publish"); - } - - @Test - public void testPubSubBackgroundFunction_PubSubMessage(CaptureSystemOutput.OutputCapture outputCapture) { - PubSubMessage pubSubMessage = new PubSubMessage(); - pubSubMessage.setMessageId("1234"); - pubSubMessage.setData("Hello"); - testBackgroundFunction(outputCapture, PubsubBackgroundFunctionPubSubMessage.class, pubSubMessage, null, - "Message: Hello; Type: google.pubsub.topic.publish; Message ID: 1234", "google.pubsub.topic.publish"); - } - - private void testBackgroundFunction(CaptureSystemOutput.OutputCapture outputCapture, Class configurationClass, I input, O expectedResult, - String expectedSysOut, String eventType) { - - FunctionInvoker handler = new FunctionInvoker(configurationClass); - - handler.accept(gson.toJson(input), new Context(null, null, eventType, null)); - - // verify function sysout statements - if (expectedSysOut != null) { - outputCapture.expect(Matchers.containsString(expectedSysOut)); - } - - // verify that if function had a return type, it was logged as being dropped - if (expectedResult != null) { - outputCapture.expect(Matchers.containsString(DROPPED_LOG_PREFIX + gson.toJson(expectedResult))); - } - else { - outputCapture.expect(Matchers.not(Matchers.containsString(DROPPED_LOG_PREFIX))); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class HelloWorldSupplier { - - @Bean - public Supplier supplier() { - return () -> "Hello World!"; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputFunction { - - @Bean - public Function function() { - return (in) -> "Thank you for sending the message: " + in.message; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputOutputFunction { - - @Bean - public Function> function() { - return (in) -> MessageBuilder - .withPayload(new OutgoingResponse("Thank you for sending the message: " + in.message)) - .setHeader("foo", "bar").build(); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputConsumer { - - @Bean - public Consumer function() { - return (in) -> System.out.println("Thank you for sending the message: " + in.message); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class PubsubBackgroundFunction { - - @Bean - public Consumer consumer() { - return (in) -> System.out.println("Thank you for sending the message: " + in.getData()); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class PubsubBackgroundFunctionPayload { - - @Bean - public Consumer consumerPayload() { - return (in) -> System.out.println("Thank you for sending the message: " + in.message); - } - - @Bean - public MessageConverter messageToIncomingRequestConverter(JsonMapper mapper) { - return new AbstractMessageConverter() { - - @Override - protected boolean supports(Class aClass) { - return aClass == IncomingRequest.class; - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, Object conversionHint) { - PubSubMessage pubSubMessage = mapper.fromJson(message.getPayload(), PubSubMessage.class); - return mapper.fromJson(pubSubMessage.getData(), IncomingRequest.class); - } - }; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class PubsubBackgroundFunctionStringMessage { - - @Bean - public Consumer> consumeStringMessage(JsonMapper mapper) { - return (message) -> { - PubSubMessage pubSubMessage = mapper.fromJson(message.getPayload(), PubSubMessage.class); - String payload = pubSubMessage.getData(); - - String eventType = ((Context) message.getHeaders().get("gcf_context")).eventType(); - String messageId = pubSubMessage.getMessageId(); - System.out.println("Message: " + payload + "; Type: " + eventType + "; Message ID: " + messageId); - }; - } - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class PubsubBackgroundFunctionPubSubMessage { - - @Bean - public Consumer> consumePubSubMessage() { - return (message) -> { - String payload = message.getPayload().getData(); - String eventType = ((Context) message.getHeaders().get("gcf_context")).eventType(); - String messageId = message.getPayload().getMessageId(); - System.out.println("Message: " + payload + "; Type: " + eventType + "; Message ID: " + messageId); - }; - } - - } - - public static class IncomingRequest { - - String message; - - public IncomingRequest(String message) { - this.message = message; - } - - public IncomingRequest() { - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } - - public static class OutgoingResponse { - - String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - OutgoingResponse(String message) { - this.message = message; - } - - public OutgoingResponse() { - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerHttpTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerHttpTests.java deleted file mode 100644 index c178414ae..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/FunctionInvokerHttpTests.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2020-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.gcp; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.google.cloud.functions.HttpRequest; -import com.google.cloud.functions.HttpResponse; -import com.google.gson.Gson; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; - -import org.springframework.boot.test.system.CapturedOutput; -import org.springframework.boot.test.system.OutputCaptureExtension; -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.MessageBuilder; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * Unit tests for the HTTP functions adapter for Google Cloud Functions. - * - * @author Dmitry Solomakha - * @author Mike Eltsufin - */ - -@ExtendWith(OutputCaptureExtension.class) -public class FunctionInvokerHttpTests { - - private static final Gson gson = new Gson(); - private HttpRequest request; - private HttpResponse response; - private BufferedWriter bufferedWriter; - private StringWriter writer; - - @BeforeEach - void testSetup() throws IOException { - request = Mockito.mock(HttpRequest.class); - response = Mockito.mock(HttpResponse.class); - writer = new StringWriter(); - bufferedWriter = new BufferedWriter(writer); - when(response.getWriter()).thenReturn(bufferedWriter); - } - - @Test - public void testHelloWorldSupplier() throws Exception { - - String expectedOutput = "Hello World!"; - FunctionInvoker handler = new FunctionInvoker(HelloWorldSupplier.class); - - handler.service(request, response); - bufferedWriter.close(); - - - assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput)); - - - } - - - @Test - public void testJsonInputFunction() throws Exception { - - FunctionInvoker handler = new FunctionInvoker(JsonInputFunction.class); - - String expectedOutput = "Thank you for sending the message: hello"; - IncomingRequest input = new IncomingRequest("hello"); - - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - - assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput)); - } - - @Test - public void testWithKanji() throws Exception { - - FunctionInvoker handler = new FunctionInvoker(JsonInputFunction.class); - - String expectedOutput = "Thank you for sending the message: 森林"; - IncomingRequest input = new IncomingRequest("森林"); - - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - - assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput)); - } - - @Test - public void testJsonInputOutputFunction() throws Exception { - - FunctionInvoker handler = new FunctionInvoker(JsonInputOutputFunction.class); - - OutgoingResponse expectedOutput = new OutgoingResponse("Thank you for sending the message: hello"); - IncomingRequest input = new IncomingRequest("hello"); - - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - - assertThat(writer.toString()).isEqualTo(gson.toJson(expectedOutput)); - - - } - - @Test - public void testJsonInputConsumer_Background(CapturedOutput capturedOutput) throws Exception { - - FunctionInvoker handler = new FunctionInvoker(JsonInputConsumer.class); - - IncomingRequest input = new IncomingRequest("hello"); - - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - assertThat(capturedOutput.toString()).contains("Thank you for sending the message: hello"); - - } - - @Test - public void testStatusCodeSet() throws Exception { - - FunctionInvoker handler = new FunctionInvoker(StatusCodeSupplier.class); - String input = "hello"; - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - verify(response).setStatusCode(404); - - } - - @Test - public void testMultiValueHeaderSupplied() throws Exception { - - FunctionInvoker handler = new FunctionInvoker(MultiValueHeaderSupplier.class); - String input = "hello"; - when(request.getReader()).thenReturn(new BufferedReader(new StringReader(gson.toJson(input)))); - handler.service(request, response); - bufferedWriter.close(); - - verify(response).appendHeader("multiValueHeader", "123,headerThing"); - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class HelloWorldSupplier { - - @Bean - public Supplier supplier() { - return () -> "Hello World!"; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class StatusCodeSupplier { - - @Bean - public Function> function() { - - String payload = "hello"; - - Message msg = MessageBuilder.withPayload(payload).setHeader("statusCode", 404) - .build(); - - return x -> msg; - }; - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class MultiValueHeaderSupplier { - - @Bean - public Function> function() { - - String payload = "hello"; - List li = new ArrayList(asList(123, "headerThing")); - - Message msg = MessageBuilder.withPayload(payload).setHeader("multiValueHeader", li) - .build(); - - return x -> msg; - }; - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputFunction { - - @Bean - public Function function() { - return (in) -> "Thank you for sending the message: " + in.message; - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputOutputFunction { - - @Bean - public Function> function() { - return (in) -> { - return MessageBuilder - .withPayload(new OutgoingResponse("Thank you for sending the message: " + in.message)) - .setHeader("foo", "bar").build(); - }; - } - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - protected static class JsonInputConsumer { - - @Bean - public Consumer function() { - return (in) -> System.out.println("Thank you for sending the message: " + in.message); - } - - } - - public static class IncomingRequest { - - String message; - - public IncomingRequest(String message) { - this.message = message; - } - - public IncomingRequest() { - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - } - - public static class OutgoingResponse { - - String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - OutgoingResponse(String message) { - this.message = message; - } - - public OutgoingResponse() { - } - - } - - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/PubSubMessage.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/PubSubMessage.java deleted file mode 100644 index aa1322348..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/PubSubMessage.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020-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.gcp; - -import java.util.Map; - -/** - * A class that can be mapped to the GCF Pub/Sub Message event type. This is for use in - * the background functions. - * - * @author Mike Eltsufin - * @since 3.0.5 - */ -public class PubSubMessage { - - private String data; - - private Map attributes; - - private String messageId; - - private String publishTime; - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public String getMessageId() { - return messageId; - } - - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - public String getPublishTime() { - return publishTime; - } - - public void setPublishTime(String publishTime) { - this.publishTime = publishTime; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/FunctionInvokerIntegrationTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/FunctionInvokerIntegrationTests.java deleted file mode 100644 index 054de3b1f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/FunctionInvokerIntegrationTests.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2020-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.gcp.integration; - -import java.io.IOException; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.web.client.TestRestTemplate; -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.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.function.adapter.gcp.integration.LocalServerTestSupport.verify; - -/** - * Integration tests for GCF Http Functions. - * - * @author Daniel Zou - * @author Mike Eltsufin - */ -public class FunctionInvokerIntegrationTests { - - @Test - public void testSingular() { - verify(CloudFunctionMainSingular.class, null, "hello", "HELLO"); - } - - @Test - public void testUppercase() throws InterruptedException, IOException { - verify(CloudFunctionMain.class, "uppercase", "hello", "HELLO"); - - } - - @Test - public void testFooBar() { - verify(CloudFunctionMain.class, "foobar", new Foo("Hi"), new Bar("Hi")); - } - - @Test - public void testErrorResponse() { - try (LocalServerTestSupport.ServerProcess serverProcess = - LocalServerTestSupport.startServer(ErrorFunction.class, "errorFunction")) { - - TestRestTemplate testRestTemplate = new TestRestTemplate(); - - HttpHeaders headers = new HttpHeaders(); - ResponseEntity response = testRestTemplate.postForEntity( - "http://localhost:" + serverProcess.getPort(), new HttpEntity<>("test", headers), - String.class); - - assertThat(response.getStatusCode().is5xxServerError()).isTrue(); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * An example function which throws an error to test response code propagation. - */ - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - static class ErrorFunction { - - @Bean - Supplier errorFunction() { - return () -> { - throw new RuntimeException(); - }; - } - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - static class CloudFunctionMainSingular { - - @Bean - Function uppercase() { - return input -> input.toUpperCase(); - } - - } - - @Configuration - @Import({ ContextFunctionCatalogAutoConfiguration.class }) - static class CloudFunctionMain { - - @Bean - Function uppercase() { - return input -> input.toUpperCase(); - } - - @Bean - Function foobar() { - return input -> new Bar(input.value); - } - - } - - public static class Foo { - - String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Foo() { - } - - Foo(String value) { - this.value = value; - } - - } - - public static class Bar { - - String value; - - Bar(String value) { - this.value = value; - } - - Bar() { - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/LocalServerTestSupport.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/LocalServerTestSupport.java deleted file mode 100644 index aa98eca30..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp/src/test/java/org/springframework/cloud/function/adapter/gcp/integration/LocalServerTestSupport.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2020-2022 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.gcp.integration; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import com.google.cloud.functions.invoker.runner.Invoker; -import com.google.gson.Gson; - -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.adapter.gcp.FunctionInvoker; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test support class for running tests on the local Cloud Function server. - * - * @author Daniel Zou - * @author Mike Eltsufin - * @author Chris Bono - */ -final public class LocalServerTestSupport { - - private static final Gson gson = new Gson(); - - private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(); - - private static final String SERVER_READY_STRING = "Started ServerConnector"; - - private LocalServerTestSupport() { - } - - /** - * Starts up the Cloud Function Server and executes the test. - */ - public static void verify(Class mainClass, String function, I input, O expectedOutput) { - try (ServerProcess serverProcess = LocalServerTestSupport.startServer(mainClass, function)) { - TestRestTemplate testRestTemplate = new TestRestTemplate(); - - HttpHeaders headers = new HttpHeaders(); - - ResponseEntity response = testRestTemplate.postForEntity( - "http://localhost:" + serverProcess.getPort(), new HttpEntity<>(gson.toJson(input), headers), - String.class); - - assertThat(response.getBody()).isEqualTo(gson.toJson(expectedOutput)); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - static ServerProcess startServer(Class springApplicationMainClass, String function) throws IOException { - String signatureType = "http"; - String target = FunctionInvoker.class.getCanonicalName(); - - File javaHome = new File(System.getProperty("java.home")); - assertThat(javaHome.exists()).isTrue(); - File javaBin = new File(javaHome, "bin"); - File javaCommand = new File(javaBin, "java"); - assertThat(javaCommand.exists()).isTrue(); - String myClassPath = System.getProperty("java.class.path"); - assertThat(myClassPath).isNotNull(); - - List command = new ArrayList<>(); - command.addAll(Arrays.asList(javaCommand.toString(), "-classpath", myClassPath, Invoker.class.getName())); - - ProcessBuilder processBuilder = new ProcessBuilder().command(command).redirectErrorStream(true); - Map environment = new HashMap<>(); - environment.put("PORT", String.valueOf(0)); - environment.put("K_SERVICE", "test-function"); - environment.put("FUNCTION_SIGNATURE_TYPE", signatureType); - environment.put("FUNCTION_TARGET", target); - environment.put("MAIN_CLASS", springApplicationMainClass.getCanonicalName()); - if (function != null) { - environment.put("spring.cloud.function.definition", function); - } - processBuilder.environment().putAll(environment); - Process serverProcess = processBuilder.start(); - Future outputMonitorResult = EXECUTOR.submit(() -> monitorOutput(serverProcess.getInputStream())); - - int port; - try { - port = outputMonitorResult.get(5L, TimeUnit.SECONDS); - } - catch (Exception ex) { - serverProcess.destroy(); - throw new AssertionError("Server never became ready"); - } - return new ServerProcess(serverProcess, port); - } - - private static Integer monitorOutput(InputStream processOutput) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(processOutput))) { - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - if (line.contains(SERVER_READY_STRING)) { - // Started ServerConnector@192b07fd{HTTP/1.1,[http/1.1]}{0.0.0.0:59259} - String portStr = line.substring(line.lastIndexOf(':') + 1, line.lastIndexOf('}')); - return Integer.parseInt(portStr); - } - if (line.contains("WARNING")) { - throw new AssertionError("Found warning in server output:\n" + line); - } - } - } - catch (IOException e) { - throw new UncheckedIOException(e); - } - throw new RuntimeException("End of input stream and server never became ready"); - } - - static class ServerProcess implements AutoCloseable { - - private final Process process; - - private final int port; - - ServerProcess(Process process, int port) { - this.process = process; - this.port = port; - } - - Process process() { - return process; - } - - @Override - public void close() { - process().destroy(); - } - - public int getPort() { - return port; - } - - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.gitignore b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index abd303b67..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/README.md b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/README.md deleted file mode 100644 index 803e84caa..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Spring Cloud Function gRPC extension to support CloudEvent proto. - -This extension project designed as an extension to general Spring Cloud Function gRPC support to specifically suport -[CloudEvent proto](https://github.com/cloudevents/spec/blob/v1.0.1/spec.proto) - -To use it simply import it as a dependency to your project together with - -```xml - - org.springframework.cloud - spring-cloud-function-grpc - -``` - -Your project should also explicitly import [CloudEvent proto](https://github.com/cloudevents/spec/blob/v1.0.1/spec.proto) and -service proto - -``` -syntax = "proto3"; - -package io.cloudevents.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; -import "CloudEvent.proto"; - -service CloudEventService { - rpc biStream(stream io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc clientStream(stream io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); - - rpc serverStream(io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc requestReply(io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); -} -``` - -Once done, you can send/receive CloudEvent messages - -You can also reference [this sample](https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-grpc-cloudevent) diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw.cmd b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% 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 deleted file mode 100644 index f0e8c7631..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/pom.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - spring-cloud-function-grpc-cloudevent-ext - spring-cloud-function-grpc-cloudevent-ext - CloudEvent extension for spring-cloud-function-grpc - - 1.55.1 - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-function-grpc - ${project.version} - - - io.grpc - grpc-stub - ${grpc.version} - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - kr.motd.maven - os-maven-plugin - 1.6.1 - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.6.1 - - - com.google.protobuf:protoc:3.23.0:exe:${os.detected.classifier} - - grpc-java - - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - - compile - compile-custom - - - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventGrpcAutoConfiguration.java b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventGrpcAutoConfiguration.java deleted file mode 100644 index 65c381fc6..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventGrpcAutoConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021-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.grpc.ce; - -import io.grpc.BindableService; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.function.grpc.MessageHandlingHelper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * - * @author Oleg Zhurakousky - * - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnProperty(name = "spring.cloud.function.grpc.server", havingValue = "true", matchIfMissing = true) -public class CloudEventGrpcAutoConfiguration { - - @SuppressWarnings("rawtypes") - @Bean - public BindableService cloudEventMessageHandler(MessageHandlingHelper helper) { - return new CloudEventHandler(helper); - } - - @Bean - @ConditionalOnMissingBean - public CloudEventMessageConverter cloudEventMessageConverter() { - return new CloudEventMessageConverter(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventHandler.java b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventHandler.java deleted file mode 100644 index 90be0bda1..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021-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.grpc.ce; - -import io.cloudevents.v1.CloudEventServiceGrpc.CloudEventServiceImplBase; -import io.cloudevents.v1.proto.CloudEvent; -import io.grpc.stub.StreamObserver; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.grpc.MessageHandlingHelper; - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - * - */ -@SuppressWarnings("rawtypes") -class CloudEventHandler extends CloudEventServiceImplBase { - - private Log logger = LogFactory.getLog(CloudEventHandler.class); - - private final MessageHandlingHelper helper; - - - - CloudEventHandler(MessageHandlingHelper helper) { - this.helper = helper; - } - - - @SuppressWarnings("unchecked") - @Override - public void requestReply(CloudEvent request, StreamObserver responseObserver) { - this.helper.requestReply(request, responseObserver); - } -} - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventMessageConverter.java b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventMessageConverter.java deleted file mode 100644 index b8bc95a72..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/java/org/springframework/cloud/function/grpc/ce/CloudEventMessageConverter.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2021-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.grpc.ce; - -import java.util.Map.Entry; - -import com.google.protobuf.ByteString; -import com.google.protobuf.GeneratedMessageV3; -import io.cloudevents.v1.proto.CloudEvent; -import io.cloudevents.v1.proto.CloudEvent.Builder; -import io.cloudevents.v1.proto.CloudEvent.CloudEventAttributeValue; -import io.cloudevents.v1.proto.CloudEvent.CloudEventAttributeValue.AttrCase; - -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.cloud.function.grpc.AbstractGrpcMessageConverter; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class CloudEventMessageConverter extends AbstractGrpcMessageConverter { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - protected Message doToSpringMessage(CloudEvent cloudEvent) { - MessageBuilder builder = MessageBuilder.withPayload(cloudEvent.getTextData()); - builder.setHeader(CloudEventMessageUtils.TYPE, cloudEvent.getType()); - builder.setHeader(CloudEventMessageUtils.SOURCE, cloudEvent.getSource()); - builder.setHeader(CloudEventMessageUtils.ID, cloudEvent.getId()); - builder.setHeader(CloudEventMessageUtils.SPECVERSION, cloudEvent.getId()); - - for (Entry attributeEntry : cloudEvent.getAttributesMap().entrySet()) { - AttrCase attrCase = attributeEntry.getValue().getAttrCase(); - if (attrCase.equals(AttrCase.CE_BOOLEAN)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeBoolean()); - } - else if (attrCase.equals(AttrCase.CE_BYTES)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeBytes()); - } - else if (attrCase.equals(AttrCase.CE_INTEGER)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeInteger()); - } - else if (attrCase.equals(AttrCase.CE_STRING)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeString()); - } - else if (attrCase.equals(AttrCase.CE_TIMESTAMP)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeTimestamp()); - } - else if (attrCase.equals(AttrCase.CE_URI)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeUri()); - } - else if (attrCase.equals(AttrCase.CE_URI_REF)) { - builder.setHeader(attributeEntry.getKey(), attributeEntry.getValue().getCeUriRef()); - } - else { - throw new IllegalStateException("Unknown type for attribute " + attributeEntry.getKey()); - } - - } - return builder.build(); - } - - @Override - protected CloudEvent doFromSpringMessage(Message springMessage) { - Builder builder = CloudEvent.newBuilder() - .setTextDataBytes(ByteString.copyFrom(springMessage.getPayload())) - .setType(CloudEventMessageUtils.getType(springMessage)) - .setSource(CloudEventMessageUtils.getSource(springMessage).toString()) - .setId(CloudEventMessageUtils.getId(springMessage)) - .setSpecVersion(CloudEventMessageUtils.getSpecVersion(springMessage)); - - - for (Entry entry : springMessage.getHeaders().entrySet()) { - builder.putAttributes(entry.getKey(), CloudEventAttributeValue.newBuilder().setCeString(entry.getValue().toString()).build()); - } - return builder.build(); - - } - - @Override - protected boolean supports(Class grpcClass) { - return grpcClass.isAssignableFrom(CloudEvent.class); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEvent.proto b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEvent.proto deleted file mode 100644 index 7952c1f79..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEvent.proto +++ /dev/null @@ -1,49 +0,0 @@ -syntax = "proto3"; - -package io.cloudevents.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "cloudevents.io/genproto/v1"; -option java_package = "io.cloudevents.v1.proto"; -option java_multiple_files = true; - -message CloudEvent { - - // -- CloudEvent Context Attributes - - // Required Attributes - string id = 1; - string source = 2; // URI-reference - string spec_version = 3; - string type = 4; - - // Optional & Extension Attributes - map attributes = 5; - - // -- CloudEvent Data (Bytes, Text, or Proto) - oneof data { - bytes binary_data = 6; - string text_data = 7; - google.protobuf.Any proto_data = 8; - } - - /** - * The CloudEvent specification defines - * seven attribute value types... - */ - - message CloudEventAttributeValue { - - oneof attr { - bool ce_boolean = 1; - int32 ce_integer = 2; - string ce_string = 3; - bytes ce_bytes = 4; - string ce_uri = 5; - string ce_uri_ref = 6; - google.protobuf.Timestamp ce_timestamp = 7; - } - } -} \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEventService.proto b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEventService.proto deleted file mode 100644 index 1a7be6a74..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/proto/CloudEventService.proto +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "proto3"; - -package io.cloudevents.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; -import "CloudEvent.proto"; - -service CloudEventService { - rpc biStream(stream io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc clientStream(stream io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); - - rpc serverStream(io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc requestReply(io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); -} \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 4c9640b55..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.grpc.ce.CloudEventGrpcAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/application.properties b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/test/java/org/springframework/cloud/grpc/ce/SpringCloudFunctionGrpcCloudeventApplicationTests.java b/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/test/java/org/springframework/cloud/grpc/ce/SpringCloudFunctionGrpcCloudeventApplicationTests.java deleted file mode 100644 index 8ab26e6bd..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext/src/test/java/org/springframework/cloud/grpc/ce/SpringCloudFunctionGrpcCloudeventApplicationTests.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021-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.grpc.ce; - -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SpringCloudFunctionGrpcCloudeventApplicationTests { - -// @Test -// void contextLoads() { -// } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/.jdk8 b/spring-cloud-function-adapters/spring-cloud-function-grpc/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/README.md b/spring-cloud-function-adapters/spring-cloud-function-grpc/README.md deleted file mode 100644 index 57b6d7ce5..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/README.md +++ /dev/null @@ -1,233 +0,0 @@ -### Introduction - -Spring Cloud Function allows you to invoke function via [gRPC](https://grpc.io/). While you can read more about gRPC in te provided link, this section will describe the parts relevant to Spring Cloud Function integration. - -As with all other Spring-boot based frameworks all you need to do is add `spring-cloud-function-grpc` dependency to your POM. -```xml - - org.springframework.cloud - spring-cloud-function-grpc - ${current.version} - -``` - -### Programming model - -#### Two operation modes (client/server) -Spring Cloud Function gRPC support provides two modes of operation - _client_ and _server_. In other words when you add `spring-cloud-function-grpc` dependency to your POM you may or may not want the gRPC server as you may -only be interested in client-side utilities to invoke a function exposed via gRPC server running on some host/port. -To support these two modes Spring Cloud Function provides `spring.cloud.function.grpc.server` which defaults to `true`. -This means that the default mode of operation is _server_, since the core intention of our current gRPC support is to expose user Functions via gRPC. However, if you're only inteersted in using client-side utilities (e.g., `GrpcUtils` to help to invoke a function or convert `GrpcMessage` to Spring `Message` and vice versa), you can set this property to `false`. - -In the server (default) mode, te gRPC server would be bound to te default port ***6048***. You can change it by providing -`spring.cloud.function.grpc.port` property. - -#### Core Data and Service -At the center of gRPC and Spring Cloud Function integration is a canonical protobuff structure - `GrpcMessage`. It is modeled after Spring [Message](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/messaging/Message.html). - -``` -message GrpcSpringMessage { - bytes payload = 1; - map headers = 2; -} -``` -As you can see it is a very generic structure which can support any type of data amd metadata you wish to exchange. - -It also defines a `MessagingService` allowing you to generate required stubs to support true plolyglot nature of gRPC. - -``` -service MessagingService { - rpc biStream(stream GrpcSpringMessage) returns (stream GrpcSpringMessage); - - rpc clientStream(stream GrpcSpringMessage) returns (GrpcSpringMessage); - - rpc serverStream(GrpcSpringMessage) returns (stream GrpcSpringMessage); - - rpc requestReply(GrpcSpringMessage) returns (GrpcSpringMessage); -} -``` -That said, when using Java, you do not need to generate anything, rather identify function definition and send and receive Spring `Messages`. -You can get a pretty good idea from this [test case](https://github.com/spring-cloud/spring-cloud-function/blob/82e2583acd7c8aaaf2bc5ec935d486a336e97ae7/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java#L49). - -#### 4 Interaction RPC Modes - -The gRPC provides 4 interaction modes -* Reques/Repply RPC -* Server-side streaming RPC -* Client-side streaming RPC -* Bi-directional streaming RPC - -Spring Cloud Function provides support for all 4 of them. - -##### Request Reply RPC -The most straight forward interaction mode is _Request/Reply_. -Suppose you have a function - -```java -@EnableAutoConfiguration -public static class SampleConfiguration { - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } -} -``` -After identifying this function via `spring.cloud.function.definition` property (see example [here](https://github.com/spring-cloud/spring-cloud-function/blob/ded02fec0a6d3d66b8ec00f99f28be2a4bbec668/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java)), -you can invoke it using utility method(s) provided in `GrpcUtils` class - -```java -Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .build(); -Message reply = GrpcUtils.requestReply(message); -``` - -You can also provide `spring.cloud.function.definition` property via `Message` headers, to support more dynamic cases. - -```java -Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader("spring.cloud.function.definition", "reverse") - .build(); -``` - -##### Server-side streaming RPC -The Server-side streaming RPC allows you to reply with the stream of data. - -```java -@EnableAutoConfiguration -public static class SampleConfiguration { - @Bean - public Function> stringInStreamOut() { - return value -> Flux.just(value, value.toUpperCase()); - } -} -``` -After identifying this function via `spring.cloud.function.definition` property (see example [here](https://github.com/spring-cloud/spring-cloud-function/blob/ded02fec0a6d3d66b8ec00f99f28be2a4bbec668/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java)), -you can invoke it using utility method(s) provided in `GrpcUtils` class - -```java -Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()).setHeader("foo", "bar").build(); - -Flux> reply = - GrpcUtils.serverStream("localhost", FunctionGrpcProperties.GRPC_PORT, message); - -List> results = reply.collectList().block(Duration.ofSeconds(5)); -``` - -You can see that gRPC stream is mapped to instance of `Flux` from [project reactor](https://projectreactor.io/) - -Similarly to the _request/reply_ you can also provide `spring.cloud.function.definition` property via `Message` headers, to support more dynamic cases. - -```java -Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader("spring.cloud.function.definition", "reverse") - .build(); -``` - -##### Client-side streaming RPC -The Client-side streaming RPC allows you to stream input data and receive a single reply. - -```java -@EnableAutoConfiguration -public static class SampleConfiguration { - @Bean - public Function, String> streamInStringOut() { - return flux -> flux.doOnNext(v -> { - try { - // do something useful - Thread.sleep(new Random().nextInt(2000)); // artificial delay - } - catch (Exception e) { - // ignore - } - }).collectList().block().toString(); - } -} -``` -After identifying this function via `spring.cloud.function.definition` property (see example [here](https://github.com/spring-cloud/spring-cloud-function/blob/ded02fec0a6d3d66b8ec00f99f28be2a4bbec668/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java)), -you can invoke it using utility method(s) provided in `GrpcUtils` class - -```java -List> messages = new ArrayList<>(); -messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); -messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); -messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - -Message reply = - GrpcUtils.clientStream("localhost", FunctionGrpcProperties.GRPC_PORT, Flux.fromIterable(messages)); - -``` - -You can see that gRPC stream is mapped to instance of `Flux` from [project reactor](https://projectreactor.io/) - -Unlike the _request/reply_ and _server-side streaming_, you can ONLY pass function definition via property or environment variable. - -##### Bi-Directional streaming RPC -The bi-directional streaming RPC allows you to stream input and output data. - -```java -@EnableAutoConfiguration -public static class SampleConfiguration { - @Bean - public Function, Flux> uppercaseReactive() { - return flux -> flux.map(v -> v.toUpperCase()); - } -} -``` -After identifying this function via `spring.cloud.function.definition` property (see example [here](https://github.com/spring-cloud/spring-cloud-function/blob/ded02fec0a6d3d66b8ec00f99f28be2a4bbec668/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java)), -you can invoke it using utility method(s) provided in `GrpcUtils` class - -```java -List> messages = new ArrayList<>(); -messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); -messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); -messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - -Flux> clientResponseObserver = - GrpcUtils.biStreaming("localhost", FunctionGrpcProperties.GRPC_PORT, Flux.fromIterable(messages)); - -List> results = clientResponseObserver.collectList().block(Duration.ofSeconds(1)); -``` - -You can see that gRPC stream is mapped to instance of `Flux` from [project reactor](https://projectreactor.io/) - -Unlike the _request/reply_ and _server-side streaming_, you can ONLY pass function definition via property or environment variable. - -#### Pluggable protobuf extension - -While the core data object and its corresponding schema <> are modeled after Spring Message and can represent -virtually any object, there are times when you may want to plug-in your own protobuf services. - -Spring Cloud Function provides such support by allowing you to develop extensions, which once exist could be enabled by simply -including its dependency in the POM. Such extensions are just another spring-boot project that has dependency on `spring-cloud-function-grpc` - -```xml - - org.springframework.cloud - spring-cloud-function-grpc - -``` - -It must also contain 3 classes; 1) Its configuration class, 2) Type converter for the actual protobuf 'message'and 3) Service handler -where you would normally implement your handling functionality. However instead of implementing full functionality you can model your service -after MessagingService provided by us and if you do you can rely on the existing implementation of the core interaction models provided by gRPC - -In fact Spring Cloud Function provides one of such extensions to support [Cloud Events](https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-grpc-cloudevent-ext) proto, so you can model yours after it. - -#### Multiple services on classpath - -With the protobuf extension mentioned in the previous section you may very well end up with several services on the classpath. -By default each available service will be enabled. However, if your intention is to only use one, you can specify which one by providing -its class name via `spring.cloud.function.grpc.service-class-name` property: - -``` ---spring.cloud.function.grpc.service-class-name=org.springframework.cloud.function.grpc.ce.CloudEventHandler -``` \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml deleted file mode 100644 index ab216bea5..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/pom.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - 4.0.0 - spring-cloud-function-grpc - jar - spring-cloud-function-grpc - Spring Cloud Function gRPC Support - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - - 1.55.1 - true - - - - javax.annotation - javax.annotation-api - 1.3.2 - - - io.grpc - grpc-netty - ${grpc.version} - - - io.grpc - grpc-protobuf - ${grpc.version} - - - io.grpc - grpc-services - ${grpc.version} - - - io.grpc - grpc-stub - ${grpc.version} - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - org.awaitility - awaitility - test - - - - - - kr.motd.maven - os-maven-plugin - 1.6.1 - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.6.1 - - - com.google.protobuf:protoc:3.23.0:exe:${os.detected.classifier} - - grpc-java - - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - - compile - compile-custom - - - - - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/AbstractGrpcMessageConverter.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/AbstractGrpcMessageConverter.java deleted file mode 100644 index 7a8a76fda..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/AbstractGrpcMessageConverter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import org.springframework.messaging.Message; - -import com.google.protobuf.GeneratedMessageV3; - -/** - * - * @author Oleg Zhurakousky - * - * @param instance of {@link GeneratedMessageV3} - */ -public abstract class AbstractGrpcMessageConverter implements GrpcMessageConverter { - - @Override - public Message toSpringMessage(T grpcMessage) { - if (this.supports(grpcMessage)) { - return this.doToSpringMessage(grpcMessage); - } - return null; - } - - @Override - public T fromSpringMessage(Message springMessage, Class grpcClass) { - if (this.supports(grpcClass)) { - return this.doFromSpringMessage(springMessage); - } - return null; - } - - protected abstract Message doToSpringMessage(T grpcMessage); - - - protected abstract T doFromSpringMessage(Message springMessage); - - protected boolean supports(T grpcMessage) { -// String fieldName = grpcMessage.getAllFields().keySet().iterator().next().getFullName(); -// fieldName = fieldName.substring(0, fieldName.lastIndexOf(".")); -// System.out.println(grpcMessage.getClass().getName()); -// return fieldName.contains(grpcMessage.getClass().getSimpleName()); - return this.supports(grpcMessage.getClass()); - } - - protected abstract boolean supports(Class grpcClass); -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/FunctionGrpcProperties.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/FunctionGrpcProperties.java deleted file mode 100644 index dd1427688..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/FunctionGrpcProperties.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.function.context.FunctionProperties; - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - * - */ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX + ".grpc") -public class FunctionGrpcProperties { - - private final static String GRPC_PREFIX = FunctionProperties.PREFIX + ".grpc"; - /** - * The name of function definition property. - */ - public final static String SERVICE_CLASS_NAME = GRPC_PREFIX + ".service-class-name"; - - /** - * Default gRPC port. - */ - public final static int GRPC_PORT = 6048; - - /** - * gRPC port server will bind to. Default 6048; - */ - private int port = GRPC_PORT; - - /** - * The fully qualified name of the service you wish to enable/expose. - * Setting this property ensures that only a single service is enabled/exposed, - * regardless of how many services are available on the classpath. - */ - private String serviceClassName; - - /** - * Grpc Server port. - */ - public int getPort() { - return this.port; - } - - public void setPort(int port) { - this.port = port; - } - - - public String getServiceClassName() { - return serviceClassName; - } - - - public void setServiceClassName(String serviceClassName) { - this.serviceClassName = serviceClassName; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcAutoConfiguration.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcAutoConfiguration.java deleted file mode 100644 index 005cbaf7f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcAutoConfiguration.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import java.util.List; - -import io.grpc.BindableService; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -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.FunctionProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(FunctionGrpcProperties.class) -@ConditionalOnProperty(name = "spring.cloud.function.grpc.server", havingValue = "true", matchIfMissing = true) -public class GrpcAutoConfiguration { - - @Bean - public GrpcServer grpcServer(FunctionGrpcProperties grpcProperties, BindableService[] grpcMessagingServices) { - Assert.notEmpty(grpcMessagingServices, "'grpcMessagingServices' must not be null or empty"); - if (StringUtils.hasText(grpcProperties.getServiceClassName())) { - for (BindableService bindableService : grpcMessagingServices) { - if (bindableService.getClass().getName().equals(grpcProperties.getServiceClassName())) { - return new GrpcServer(grpcProperties, new BindableService[] {bindableService}); - } - } - } - return new GrpcServer(grpcProperties, grpcMessagingServices); - } - - - @SuppressWarnings("rawtypes") - @Bean - @ConditionalOnMissingBean - public BindableService grpcSpringMessageHandler(MessageHandlingHelper helper) { - return new GrpcServerMessageHandler(helper); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - public MessageHandlingHelper grpcMessageHandlingHelper(List> grpcConverters, - FunctionProperties funcProperties, FunctionCatalog functionCatalog) { - return new MessageHandlingHelper(grpcConverters, functionCatalog, funcProperties); - } - - @Bean - public GrpcSpringMessageConverter grpcSpringMessageConverter() { - return new GrpcSpringMessageConverter(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcClientTemplate.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcClientTemplate.java deleted file mode 100644 index 7699218d2..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcClientTemplate.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.springframework.cloud.function.grpc; - -public class GrpcClientTemplate { - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcMessageConverter.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcMessageConverter.java deleted file mode 100644 index d9ae88d75..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcMessageConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import com.google.protobuf.GeneratedMessageV3; - -import org.springframework.messaging.Message; - -/** - * - * @author Oleg Zhurakousky - * - * @param instance of {@link GeneratedMessageV3} - */ -public interface GrpcMessageConverter { - - Message toSpringMessage(T grpcMessage); - - T fromSpringMessage(Message springMessage, Class grpcClass); -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServer.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServer.java deleted file mode 100644 index feecafe38..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServer.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2021-2022 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.grpc; - -import java.util.Collections; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import io.grpc.BindableService; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.grpc.protobuf.services.ProtoReflectionService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.context.EnvironmentAware; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.util.ClassUtils; - -/** - * - * @author Oleg Zhurakousky - * @author Dave Syer - * @author Chris Bono - * - * @since 3.2 - * - */ -class GrpcServer implements SmartLifecycle, EnvironmentAware { - - private Log logger = LogFactory.getLog(GrpcServer.class); - - private final FunctionGrpcProperties grpcProperties; - - private final BindableService[] grpcMessageServices; - - private final ExecutorService executor = Executors.newSingleThreadExecutor(); - - private Server server; - - private Environment environment; - - GrpcServer(FunctionGrpcProperties grpcProperties, BindableService[] grpcMessageServices) { - this.grpcProperties = grpcProperties; - this.grpcMessageServices = grpcMessageServices; - } - - @Override - public void start() { - this.executor.execute(() -> { - try { - ServerBuilder serverBuilder = ServerBuilder.forPort(this.grpcProperties.getPort()); - for (int i = 0; i < this.grpcMessageServices.length; i++) { - BindableService bindableService = this.grpcMessageServices[i]; - serverBuilder.addService(bindableService); - } - if (ClassUtils.isPresent("io.grpc.protobuf.services.ProtoReflectionService", null)) { - serverBuilder.addService(ProtoReflectionService.newInstance()); - } - this.server = serverBuilder.build(); - - logger.info("Starting gRPC server"); - this.server.start(); - logger.info("gRPC server is listening on port " + this.server.getPort()); - - if (environment instanceof ConfigurableEnvironment) { - ((ConfigurableEnvironment) this.environment).getPropertySources().addFirst( - new MapPropertySource("grpcServerProps", Collections.singletonMap("local.grpc.server.port", server.getPort()))); - } - } - catch (Exception e) { - stop(); - throw new IllegalStateException(e); - } - }); - } - - @Override - public void stop() { - logger.info("Shutting down gRPC server"); - this.server.shutdownNow(); - this.executor.shutdownNow(); - } - - @Override - public boolean isRunning() { - return this.server != null && !this.server.isShutdown(); - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServerMessageHandler.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServerMessageHandler.java deleted file mode 100644 index f04405846..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcServerMessageHandler.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2021-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. - */ - -/* - * Copyright 2021-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.grpc; - -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -// -import io.grpc.Status; -import io.grpc.stub.ServerCallStreamObserver; -import io.grpc.stub.StreamObserver; -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.Sinks; -import reactor.core.publisher.Sinks.Many; -// -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.grpc.MessagingServiceGrpc.MessagingServiceImplBase; -import org.springframework.context.SmartLifecycle; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -import com.google.protobuf.GeneratedMessageV3; -// -//import com.google.protobuf.GeneratedMessage; - - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - * - */ -@SuppressWarnings("rawtypes") -public class GrpcServerMessageHandler extends MessagingServiceImplBase { - - private Log logger = LogFactory.getLog(GrpcServerMessageHandler.class); - - private final MessageHandlingHelper helper; - - private boolean running; - - public GrpcServerMessageHandler(MessageHandlingHelper helper) { - this.helper = helper; - } - - @Override - @SuppressWarnings("unchecked") - public void requestReply(GrpcSpringMessage request, StreamObserver responseObserver) { - this.helper.requestReply(request, responseObserver); - } - - @Override - @SuppressWarnings("unchecked") - public void serverStream(GrpcSpringMessage request, StreamObserver responseObserver) { - this.helper.serverStream(request, responseObserver); - } - - @Override - @SuppressWarnings("unchecked") - public StreamObserver clientStream(StreamObserver responseObserver) { - return this.helper.clientStream(responseObserver, GrpcSpringMessage.class); - } - - @SuppressWarnings("unchecked") - @Override - public StreamObserver biStream(StreamObserver responseObserver) { - return this.helper.biStream(responseObserver, GrpcSpringMessage.class); - } -} - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcSpringMessageConverter.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcSpringMessageConverter.java deleted file mode 100644 index 249cbb80b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcSpringMessageConverter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import com.google.protobuf.ByteString; -import com.google.protobuf.GeneratedMessageV3; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class GrpcSpringMessageConverter extends AbstractGrpcMessageConverter { - - @Override - protected Message doToSpringMessage(GrpcSpringMessage grpcMessage) { - return MessageBuilder.withPayload(grpcMessage.getPayload().toByteArray()) - .copyHeaders(grpcMessage.getHeadersMap()) - .build(); - } - - @Override - protected GrpcSpringMessage doFromSpringMessage(Message springMessage) { - Map stringHeaders = new HashMap<>(); - springMessage.getHeaders().forEach((k, v) -> { - stringHeaders.put(k, v.toString()); - }); - return GrpcSpringMessage.newBuilder() - .setPayload(ByteString.copyFrom(springMessage.getPayload())) - .putAllHeaders(stringHeaders) - .build(); - } - - @Override - protected boolean supports(Class grpcClass) { - return grpcClass.isAssignableFrom(GrpcSpringMessage.class); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcUtils.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcUtils.java deleted file mode 100644 index 7ed7d7117..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/GrpcUtils.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - - -import com.google.protobuf.ByteString; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Status; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ClientResponseObserver; -import io.grpc.stub.StreamObserver; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Sinks; -import reactor.core.publisher.Sinks.Many; - -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - * - */ -public final class GrpcUtils { - - private static Log logger = LogFactory.getLog(GrpcUtils.class); - - private GrpcUtils() { - - } - - public static GrpcSpringMessage toGrpcSpringMessage(byte[] payload, Map headers) { - return GrpcSpringMessage.newBuilder() - .setPayload(ByteString.copyFrom(payload)) - .putAllHeaders(headers) - .build(); - } - - public static GrpcSpringMessage toGrpcSpringMessage(Message message) { - Map stringHeaders = new HashMap<>(); - message.getHeaders().forEach((k, v) -> { - stringHeaders.put(k, v.toString()); - }); - return toGrpcSpringMessage(message.getPayload(), stringHeaders); - } - - public static Message fromGrpcSpringMessage(GrpcSpringMessage message) { - return MessageBuilder.withPayload(message.getPayload().toByteArray()) - .copyHeaders(message.getHeadersMap()) - .build(); - } - - public static Message requestReply(Message inputMessage) { - return requestReply("localhost", FunctionGrpcProperties.GRPC_PORT, inputMessage); - } - - public static Message requestReply(String host, int port, Message inputMessage) { - ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext().build(); - try { - MessagingServiceGrpc.MessagingServiceBlockingStub stub = MessagingServiceGrpc - .newBlockingStub(channel); - - try { - GrpcSpringMessage response = stub.requestReply(toGrpcSpringMessage(inputMessage)); - return fromGrpcSpringMessage(response); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - finally { - channel.shutdownNow(); - } - } - - /** - * Utility method to support bi-directional streaming interaction. Will connect to gRPC server using default host/port, - * otherwise use {@link #biStreaming(String, int, Flux)} method. - * - * Keep in mind that there is no implied relationship between input stream and output stream. - * They are completely independent where one may end before the other. - * - * @param inputStream {@code FluxMessage>} representing input stream. - * @return {@code Flux>} representing output stream - */ - public static Flux> biStreaming(Flux> inputStream) { - return biStreaming("localhost", FunctionGrpcProperties.GRPC_PORT, inputStream); - } - - /** - * Utility method to support bi-directional streaming interaction. - * Keep in mind that there is no implied relationship between input stream and output stream. - * They are completely independent where one may end before the other. - * - * @param host gRPC server host name - * @param port gRPC server port - * @param inputStream {@code FluxMessage>} representing input stream - * @return {@code Flux>} representing output stream - */ - public static Flux> biStreaming(String host, int port, Flux> inputStream) { - ManagedChannel channel = ManagedChannelBuilder - .forAddress(host, port) - .usePlaintext().build(); - MessagingServiceGrpc.MessagingServiceStub stub = MessagingServiceGrpc - .newStub(channel); - Many> sink = Sinks.many().unicast().onBackpressureBuffer(); - - ClientResponseObserver clientResponseObserver = clientResponseObserver(inputStream, sink); - - stub.biStream(clientResponseObserver); - - return sink.asFlux().doOnComplete(() -> { - logger.debug("Shutting down channel"); - channel.shutdownNow(); - }) - .doOnError(e -> { - e.printStackTrace(); - channel.shutdownNow(); - }); - } - - public static Flux> serverStream(String host, int port, Message inputMessage) { - ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext().build(); - MessagingServiceGrpc.MessagingServiceBlockingStub stub = MessagingServiceGrpc - .newBlockingStub(channel); - - Iterator serverStream = stub.serverStream(toGrpcSpringMessage(inputMessage)); - - Many> sink = Sinks.many().unicast().onBackpressureBuffer(); - ExecutorService executor = Executors.newSingleThreadExecutor(); - executor.execute(() -> { - while (serverStream.hasNext()) { - GrpcSpringMessage grpcMessage = serverStream.next(); - sink.tryEmitNext(GrpcUtils.fromGrpcSpringMessage(grpcMessage)); - } - sink.tryEmitComplete(); - }); - - return sink.asFlux() - .doOnComplete(() -> { - channel.shutdownNow(); - executor.shutdownNow(); - }) - .doOnError(e -> { - e.printStackTrace(); - channel.shutdownNow(); - executor.shutdownNow(); - }); - } - - - /** - * Utility method to support client-side streaming interaction. Will connect to gRPC server using default host/port, - * otherwise use {@link #clientStream(String, int, Flux)} method. - * - * @param inputStream {@code FluxMessage>} representing input stream. - * @return {@code Message} representing output - */ - public static Message clientStream(Flux> inputStream) { - return clientStream("localhost", FunctionGrpcProperties.GRPC_PORT, inputStream); - } - - /** - * Utility method to support client-side streaming interaction. - * - * @param host gRPC server host name - * @param port gRPC server port - * @param inputStream {@code FluxMessage>} representing input stream - * @return {@code Message} representing output - */ - public static Message clientStream(String host, int port, Flux> inputStream) { - ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port) - .usePlaintext().build(); - - LinkedBlockingQueue> resultRef = new LinkedBlockingQueue<>(1); - StreamObserver responseObserver = new StreamObserver() { - @Override - public void onNext(GrpcSpringMessage result) { - if (logger.isDebugEnabled()) { - logger.debug("Client received reply: " + result); - } - resultRef.offer(GrpcUtils.fromGrpcSpringMessage(result)); - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - channel.shutdownNow(); - } - - @Override - public void onCompleted() { - logger.info("Client completed"); - channel.shutdownNow(); - } - }; - - MessagingServiceGrpc.MessagingServiceStub asyncStub = MessagingServiceGrpc.newStub(channel); - - StreamObserver requestObserver = asyncStub.clientStream(responseObserver); - - inputStream.doOnNext(message -> { - if (logger.isDebugEnabled()) { - logger.debug("Client sending: " + message); - } - try { - requestObserver.onNext(GrpcUtils.toGrpcSpringMessage(message)); - } - catch (Exception e) { - requestObserver.onError(e); - } - }).doOnComplete(() -> { - requestObserver.onCompleted(); - }).doOnError(e -> { - e.printStackTrace(); - responseObserver.onError(Status.UNKNOWN.withDescription("Error handling request") - .withCause(e).asRuntimeException()); - }) - .subscribe(); - - try { - return resultRef.poll(Integer.MAX_VALUE, TimeUnit.MILLISECONDS); - } - catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new IllegalStateException(ie); - } - } - - private static ClientResponseObserver clientResponseObserver(Flux> inputStream, Many> sink) { - return new ClientResponseObserver() { - - ClientCallStreamObserver requestStreamObserver; - - @Override - public void beforeStart(ClientCallStreamObserver requestStreamObserver) { - this.requestStreamObserver = requestStreamObserver; - requestStreamObserver.disableAutoInboundFlowControl(); - - requestStreamObserver.setOnReadyHandler(new Runnable() { - @Override - public void run() { - inputStream - .doOnNext(request -> { - if (logger.isDebugEnabled()) { - logger.debug("Streaming message to function: " + request); - } - requestStreamObserver.onNext(GrpcUtils.toGrpcSpringMessage(request)); - }) - .doOnComplete(() -> { - requestStreamObserver.onCompleted(); - }) - .subscribe(); - } - }); - } - - @Override - public void onNext(GrpcSpringMessage message) { - if (logger.isDebugEnabled()) { - logger.debug("Streaming message from function: " + message); - } - sink.tryEmitNext(fromGrpcSpringMessage(message)); - requestStreamObserver.request(1); - - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - } - - @Override - public void onCompleted() { - logger.info("Client stream is complete"); - sink.tryEmitComplete(); // TODO revisit as this would complete the server stream simply because the client is done. - // Perhaps we need to expose some boolean value when this is desirable - } - }; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/MessageHandlingHelper.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/MessageHandlingHelper.java deleted file mode 100644 index c24e3cd4f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/java/org/springframework/cloud/function/grpc/MessageHandlingHelper.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright 2021-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.grpc; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.google.protobuf.ByteString; -import com.google.protobuf.GeneratedMessageV3; - -import io.grpc.Status; -import io.grpc.stub.ServerCallStreamObserver; -import io.grpc.stub.StreamObserver; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.publisher.Sinks; -import reactor.core.publisher.Sinks.Many; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.SmartLifecycle; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.2 - */ -public class MessageHandlingHelper implements SmartLifecycle { - - private Log logger = LogFactory.getLog(MessageHandlingHelper.class); - - private final List> grpcConverters; - - private final FunctionProperties funcProperties; - - private final FunctionCatalog functionCatalog; - - private final ExecutorService executor; - - private boolean running; - - public MessageHandlingHelper(List> grpcConverters, - FunctionCatalog functionCatalog, FunctionProperties funcProperties) { - this.grpcConverters = grpcConverters; - this.funcProperties = funcProperties; - this.functionCatalog = functionCatalog; - this.executor = Executors.newCachedThreadPool(); - } - - @SuppressWarnings("unchecked") - public void requestReply(T request, StreamObserver responseObserver) { - Message message = this.toSpringMessage(request); - FunctionInvocationWrapper function = this.resolveFunction(message.getHeaders()); - if (FunctionTypeUtils.isFlux(function.getOutputType())) { - String errorMessage = "Flux reply is not supported for `requestReply` mode"; - responseObserver.onError(Status.UNKNOWN.withDescription(errorMessage) - .withCause(new UnsupportedOperationException(errorMessage)).asRuntimeException()); - return; - } - - Object replyMessage = function.apply(message); - if (replyMessage instanceof Message) { - GeneratedMessageV3 reply = this.toGrpcMessage((Message) replyMessage, (Class) request.getClass()); - responseObserver.onNext((T) reply); - responseObserver.onCompleted(); - } - else if (replyMessage instanceof Publisher) { - if (replyMessage instanceof Mono) { - Mono.from((Publisher) replyMessage).doOnNext(reply -> { - GeneratedMessageV3 replyGrps = this.toGrpcMessage((Message) reply, (Class) request.getClass()); - responseObserver.onNext((T) replyGrps); - responseObserver.onCompleted(); - }) - .subscribe(); - } - } - } - - @SuppressWarnings("unchecked") - public void serverStream(T request, StreamObserver responseObserver) { - Message message = this.toSpringMessage(request); - FunctionInvocationWrapper function = this.resolveFunction(message.getHeaders()); - Publisher> replyStream = (Publisher>) function.apply(message); - Flux.from(replyStream).doOnNext(replyMessage -> { - responseObserver.onNext(this.toGrpcMessage(replyMessage, (Class) request.getClass())); - }) - .doOnComplete(() -> responseObserver.onCompleted()) - .subscribe(); - } - - @SuppressWarnings("unchecked") - public StreamObserver clientStream(StreamObserver responseObserver, Class grpcMessageType) { - ServerCallStreamObserver serverCallStreamObserver = (ServerCallStreamObserver) responseObserver; - serverCallStreamObserver.disableAutoInboundFlowControl(); - - FunctionInvocationWrapper function = this.resolveFunction(null); - - AtomicBoolean wasReady = new AtomicBoolean(false); - serverCallStreamObserver.setOnReadyHandler(() -> { - if (serverCallStreamObserver.isReady() && !wasReady.get()) { - wasReady.set(true); - logger.info("gRPC Server receiving stream is ready."); - serverCallStreamObserver.request(1); - } - }); - - if (!function.isInputTypePublisher()) { - throw new UnsupportedOperationException("The client streaming is " - + "not supported for functions that accept non-Publisher: " - + function); - } - else if (function.isOutputTypePublisher()) { - throw new UnsupportedOperationException("The client streaming is " - + "not supported for functions that return Publisher: " - + function); - } - else { - Many> inputStream = Sinks.many().unicast().onBackpressureBuffer(); - Flux> inputStreamFlux = inputStream.asFlux(); - - LinkedBlockingQueue> resultRef = new LinkedBlockingQueue<>(1); - this.executor.execute(() -> { - Message replyMessage = (Message) function.apply(inputStreamFlux); - if (logger.isDebugEnabled()) { - logger.debug("Function invocation reply: " + replyMessage); - } - resultRef.offer(replyMessage); - }); - - return new StreamObserver() { - @Override - public void onNext(T inputMessage) { - if (logger.isDebugEnabled()) { - logger.debug("gRPC Server receiving: " + inputMessage); - } - inputStream.tryEmitNext(toSpringMessage(inputMessage)); - serverCallStreamObserver.request(1); - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - responseObserver.onError(Status.UNKNOWN.withDescription("Error handling request") - .withCause(t).asRuntimeException()); - } - - @Override - public void onCompleted() { - logger.info("gRPC Server has finished receiving data."); - inputStream.tryEmitComplete(); - try { - responseObserver.onNext(toGrpcMessage(resultRef.poll(Integer.MAX_VALUE, TimeUnit.MILLISECONDS), grpcMessageType)); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - finally { - responseObserver.onCompleted(); - } - } - }; - } - } - - public StreamObserver biStream(StreamObserver responseObserver, Class grpcMessageType) { - ServerCallStreamObserver serverCallStreamObserver = (ServerCallStreamObserver) responseObserver; - serverCallStreamObserver.disableAutoInboundFlowControl(); - - FunctionInvocationWrapper function = this.resolveFunction(null); - - AtomicBoolean wasReady = new AtomicBoolean(false); - serverCallStreamObserver.setOnReadyHandler(() -> { - if (serverCallStreamObserver.isReady() && !wasReady.get()) { - wasReady.set(true); - logger.info("gRPC Server receiving stream is ready."); - serverCallStreamObserver.request(1); - } - }); - - if (function.isInputTypePublisher()) { - if (function.isOutputTypePublisher()) { - return this.biStreamReactive(responseObserver, serverCallStreamObserver, grpcMessageType); - } - UnsupportedOperationException ex = new UnsupportedOperationException("The bi-directional streaming is " - + "not supported for functions that accept Publisher but return non-Publisher: " - + function); - responseObserver.onCompleted(); - throw ex; - } - else { - if (!function.isOutputTypePublisher()) { - return this.biStreamImperative(responseObserver, serverCallStreamObserver, wasReady); - } - - UnsupportedOperationException ex = new UnsupportedOperationException("The bidirection streaming is " - + "not supported for functions that accept non-Publisher but return Publisher: " - + function); - responseObserver.onCompleted(); - throw ex; - } - } - - @SuppressWarnings("unchecked") - private StreamObserver biStreamReactive(StreamObserver responseObserver, - ServerCallStreamObserver serverCallStreamObserver, Class grpcMessageType) { - Many> inputStream = Sinks.many().unicast().onBackpressureBuffer(); - Flux> inputStreamFlux = inputStream.asFlux(); - - FunctionInvocationWrapper function = this.resolveFunction(null); - - Publisher> outputPublisher = (Publisher>) function.apply(inputStreamFlux); - - Flux.from(outputPublisher).subscribe(functionResult -> { - T outputMessage = toGrpcMessage(functionResult, grpcMessageType); - if (logger.isDebugEnabled()) { - logger.debug("gRPC Server replying: " + outputMessage); - } - responseObserver.onNext(outputMessage); - }); - - return new StreamObserver() { - @Override - public void onNext(T inputMessage) { - if (logger.isDebugEnabled()) { - logger.debug("gRPC Server receiving: " + inputMessage); - } - inputStream.tryEmitNext(toSpringMessage(inputMessage)); - serverCallStreamObserver.request(1); - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - inputStream.tryEmitComplete(); - responseObserver.onError(Status.UNKNOWN.withDescription("Error handling request") - .withCause(t).asException()); - } - - @Override - public void onCompleted() { - logger.info("gRPC Server has finished receiving data."); - inputStream.tryEmitComplete(); - responseObserver.onCompleted(); - } - }; - } - - private StreamObserver biStreamImperative(StreamObserver responseObserver, - ServerCallStreamObserver serverCallStreamObserver, - AtomicBoolean wasReady) { - return new StreamObserver() { - - @SuppressWarnings("unchecked") - @Override - public void onNext(T request) { - try { - Message message = toSpringMessage(request); - FunctionInvocationWrapper function = resolveFunction( - message.getHeaders()); - - Message replyMessage = (Message) function - .apply(message); - - T reply = toGrpcMessage(replyMessage, (Class) request.getClass()); - - responseObserver.onNext(reply); - - // Check the provided ServerCallStreamObserver to see if it is still - // ready to accept more messages. - if (serverCallStreamObserver.isReady()) { - serverCallStreamObserver.request(1); - } - else { - wasReady.set(false); - } - } - catch (Throwable throwable) { - throwable.printStackTrace(); - responseObserver.onError( - Status.UNKNOWN.withDescription("Error handling request") - .withCause(throwable).asException()); - } - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - responseObserver.onCompleted(); - } - - @Override - public void onCompleted() { - logger.info("gRPC Server has finished receiving data."); - responseObserver.onCompleted(); - } - }; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private T toGrpcMessage(Message request, Class grpcClass) { - for (GrpcMessageConverter converter : this.grpcConverters) { - GeneratedMessageV3 grpcMessage = converter.fromSpringMessage(request, grpcClass); - if (grpcMessage != null) { - return (T) grpcMessage; - } - } - throw new IllegalStateException("Failed to convert Grpc Message to Spring Message: " + request); - } - - @Override - public void start() { - this.running = true; - } - - @Override - public void stop() { - this.executor.shutdown(); - try { - Assert.isTrue(this.executor.awaitTermination(5000, TimeUnit.MILLISECONDS), "gRPC Server executor timed out while stopping, " - + "since there are currently executing tasks"); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - this.running = false; - } - - @Override - public boolean isRunning() { - return this.running; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private Message toSpringMessage(GeneratedMessageV3 request) { - for (GrpcMessageConverter converter : this.grpcConverters) { - Message springMessage = converter.toSpringMessage(request); - if (springMessage != null) { - return springMessage; - } - } - throw new IllegalStateException("Failed to convert Grpc Message to Spring Message: " + request); - } - - private FunctionInvocationWrapper resolveFunction(Map headers) { - String functionDefinition = funcProperties.getDefinition(); - if (!CollectionUtils.isEmpty(headers) && headers.containsKey(FunctionProperties.FUNCTION_DEFINITION)) { - functionDefinition = (String) headers.get(FunctionProperties.FUNCTION_DEFINITION); - } - FunctionInvocationWrapper function = this.functionCatalog.lookup(functionDefinition, "application/json"); - Assert.notNull(function, () -> "Failed to lookup function " + funcProperties.getDefinition()); - return function; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/proto/MessageService.proto b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/proto/MessageService.proto deleted file mode 100644 index 602be654d..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/proto/MessageService.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; -option java_multiple_files = true; -package org.springframework.cloud.function.grpc; - -message GrpcSpringMessage { - bytes payload = 1; - map headers = 2; -} - -service MessagingService { - rpc biStream(stream GrpcSpringMessage) returns (stream GrpcSpringMessage); - - rpc clientStream(stream GrpcSpringMessage) returns (GrpcSpringMessage); - - rpc serverStream(GrpcSpringMessage) returns (stream GrpcSpringMessage); - - rpc requestReply(GrpcSpringMessage) returns (GrpcSpringMessage); -} \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 1aee89ea4..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.grpc.GrpcAutoConfiguration diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java deleted file mode 100644 index ef0d66c7b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/java/org/springframework/cloud/function/grpc/GrpcInteractionTests.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2021-2022 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.grpc; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.function.Function; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.utils.SocketUtils; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - */ -@Disabled -public class GrpcInteractionTests { - - @BeforeEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - } - - @AfterEach - public void after() { - System.clearProperty("spring.cloud.function.definition"); - } - - @Test - public void testRequestReply() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=uppercase", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - - Message reply = GrpcUtils.requestReply("localhost", port, message); - - assertThat(reply.getPayload()).isEqualTo("\"HELLO GRPC\"".getBytes()); - } - } - - @Test - public void testRequestReplyWithMonoReturn() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=uppercaseMonoReturn", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - - Message reply = GrpcUtils.requestReply("localhost", port, message); - - assertThat(reply.getPayload()).isEqualTo("\"HELLO GRPC\"".getBytes()); - } - } - - @Test - public void testRequestReplyWithFluxReturn() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=uppercaseFluxReturn", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - try { - GrpcUtils.requestReply("localhost", port, message); - fail(); - } - catch (Exception e) { - assertThat(e.getMessage()).contains("Flux reply is not supported for `requestReply` mode"); - } - } - } - - @Test - public void testRequstReplyFunctionDefinitionInMessage() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - Message message = MessageBuilder.withPayload("\"hello gRPC\"".getBytes()) - .setHeader("foo", "bar") - .setHeader("spring.cloud.function.definition", "reverse") - .build(); - - Message reply = GrpcUtils.requestReply("localhost", port, message); - - assertThat(reply.getPayload()).isEqualTo("\"CPRg olleh\"".getBytes()); - } - } - - @Test - public void testBidirectionalStreamWithImperativeFunction() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=uppercase", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - List> messages = new ArrayList<>(); - messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - - Flux> clientResponseObserver = - GrpcUtils.biStreaming("localhost", port, Flux.fromIterable(messages)); - - List> results = clientResponseObserver.collectList().block(Duration.ofSeconds(10)); - assertThat(results.size()).isEqualTo(3); - assertThat(results.get(0).getPayload()).isEqualTo("\"RICKY\"".getBytes()); - assertThat(results.get(1).getPayload()).isEqualTo("\"JULIEN\"".getBytes()); - assertThat(results.get(2).getPayload()).isEqualTo("\"BUBBLES\"".getBytes()); - } - } - - @Test - public void testBidirectionalStreamWithReactiveFunction() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=uppercaseReactive", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - List> messages = new ArrayList<>(); - messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build()); - messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build()); - messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build()); - - Flux> resultStream = - GrpcUtils.biStreaming("localhost", port, Flux.fromIterable(messages)); - - List> results = resultStream.collectList().block(Duration.ofSeconds(5)); - assertThat(results.size()).isEqualTo(3); - assertThat(results.get(0).getPayload()).isEqualTo("\"RICKY\"".getBytes()); - assertThat(results.get(1).getPayload()).isEqualTo("\"JULIEN\"".getBytes()); - assertThat(results.get(2).getPayload()).isEqualTo("\"BUBBLES\"".getBytes()); - } - } - - @Test - public void testClientStreaming() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=streamInStringOut", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - List> messages = new ArrayList<>(); - messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - - Message reply = - GrpcUtils.clientStream("localhost", port, Flux.fromIterable(messages)); - - assertThat(reply.getPayload()).isEqualTo("[Ricky, Julien, Bubbles]".getBytes()); - } - } - - @Test - public void testServerStreaming() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=stringInStreamOut", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - Message message = MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar").build(); - - Flux> reply = - GrpcUtils.serverStream("localhost", port, message); - - List> results = reply.collectList().block(Duration.ofSeconds(10)); - assertThat(results.size()).isEqualTo(2); - assertThat(results.get(0).getPayload()).isEqualTo("\"Ricky\"".getBytes()); - assertThat(results.get(1).getPayload()).isEqualTo("\"RICKY\"".getBytes()); - } - } - - @Test - public void testBiStreamStreamInStringOutFailure() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=streamInStringOut", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - List> messages = new ArrayList<>(); - messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - - Flux> clientResponseObserver = - GrpcUtils.biStreaming("localhost", port, Flux.fromIterable(messages)); - - assertThat(clientResponseObserver.collectList().block(Duration.ofSeconds(2))).isEmpty(); - } - } - - @Test - public void testBiStreamStringInStreamOutFailure() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleConfiguration.class).web(WebApplicationType.NONE).run( - "--spring.jmx.enabled=false", - "--spring.cloud.function.definition=stringInStreamOut", - "--spring.cloud.function.grpc.port=0")) { - - int port = patientlyGetPort(context); - - List> messages = new ArrayList<>(); - messages.add(MessageBuilder.withPayload("\"Ricky\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Julien\"".getBytes()).setHeader("foo", "bar") - .build()); - messages.add(MessageBuilder.withPayload("\"Bubbles\"".getBytes()).setHeader("foo", "bar") - .build()); - - Flux> clientResponseObserver = - GrpcUtils.biStreaming("localhost", port, Flux.fromIterable(messages)); - - assertThat(clientResponseObserver.collectList().block(Duration.ofSeconds(2))).isEmpty(); - } - } - - private int patientlyGetPort(ConfigurableApplicationContext context) throws InterruptedException { - await() - .pollDelay(Duration.ofMillis(500)) - .pollInterval(Duration.ofMillis(500)) - .atMost(Duration.ofSeconds(3)) - .untilAsserted(() -> { - String port = context.getEnvironment().getProperty("local.grpc.server.port"); - assertThat(port).as("Unable to get 'local.grpc.server.port' - server may not have started up").isNotEmpty(); - }); - return Integer.valueOf(context.getEnvironment().getProperty("local.grpc.server.port")); - } - - @EnableAutoConfiguration - public static class SampleConfiguration { - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function> uppercaseMonoReturn() { - return v -> Mono.just(v.toUpperCase()); - } - - @Bean - public Function> uppercaseFluxReturn() { - return v -> Flux.just(v.toUpperCase(), v.toUpperCase() + "-1", v.toUpperCase() + "-2"); - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function, Flux> uppercaseReactive() { - return flux -> flux.map(v -> v.toUpperCase()); - } - - @Bean - public Function, String> streamInStringOut() { - return flux -> flux.doOnNext(v -> { - try { - Thread.sleep(new Random().nextInt(200)); // artificial delay - } - catch (Exception e) { - // ignore - } - }).collectList().block().toString(); - } - - @Bean - public Function> stringInStreamOut() { - return value -> Flux.just(value, value.toUpperCase()); - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/resources/application.properties b/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/resources/application.properties deleted file mode 100644 index 1aab44a8b..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-grpc/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -logging.level.org.springframework.cloud.function.grpc=DEBUG diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/.jdk8 b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/README.md b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/README.md deleted file mode 100644 index b5f51b0ec..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/README.md +++ /dev/null @@ -1,14 +0,0 @@ -#### Introduction - -This module represents a concept of a light weight AWS forwarding proxy which deploys and interacts with existing -Spring Boot web application deployed as AWS Lambda. - - -A sample is provided in [sample](https://github.com/spring-cloud/spring-cloud-function/tree/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store) directory. It contain README and SAM template file to simplify the deployment. This module is identified as the only additional dependnecy to the existing web-app. - -_NOTE: Although this module is AWS specific, this dependency is protocol only (not binary), therefore there is no AWS dependnecies._ - -The aformentioned proxy is identified as AWS Lambda [handler](https://github.com/spring-cloud/spring-cloud-function/blob/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store/template.yml#L14) - -The main Spring Boot configuration file is identified as [MAIN_CLASS](https://github.com/spring-cloud/spring-cloud-function/blob/serverless-web/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store/template.yml#L22) - diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/pom.xml deleted file mode 100644 index 131038ced..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - spring-cloud-function-serverless-web - jar - spring-cloud-function-serverless-web - Base serverless web adapter - - org.springframework.cloud - spring-cloud-function-adapter-parent - 4.1.0-SNAPSHOT - - - UTF-8 - UTF-8 - - - - org.springframework - spring-webmvc - - - - - org.springframework.boot - spring-boot-starter-security - provided - - - org.springframework.security - spring-security-test - test - - - - - jakarta.servlet - jakarta.servlet-api - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-web - test - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/.aws-sam/build.toml b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/.aws-sam/build.toml deleted file mode 100644 index 05c08b5fa..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/.aws-sam/build.toml +++ /dev/null @@ -1,13 +0,0 @@ -# This file is auto generated by SAM CLI build command - -[function_build_definitions] -[function_build_definitions.9341c1d5-9265-48ef-836e-25df000b0c59] -codeuri = "/Users/ozhurakousky/Documents/dev/repo/spring-cloud-function/spring-cloud-function-adapters/spring-cloud-function-adapter-aws-web/sample/pet-store" -runtime = "java11" -architecture = "x86_64" -handler = "org.springframework.cloud.function.adapter.aws.web.WebProxyInvoker::handleRequest" -manifest_hash = "" -packagetype = "Zip" -functions = ["PetStoreFunction"] - -[layer_build_definitions] diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/README.md b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/README.md deleted file mode 100644 index bbe5db289..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/README.md +++ /dev/null @@ -1,38 +0,0 @@ -Copied from https://github.com/awslabs/aws-serverless-java-container/tree/main/samples/spring/pet-store - -# Serverless Spring example -A basic pet store written with the [Spring framework](https://projects.spring.io/spring-framework/). The `StreamLambdaHandler` object is the main entry point for Lambda. - -The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yml` file in the root folder contains the application definition. - -## Pre-requisites -* [AWS CLI](https://aws.amazon.com/cli/) -* [SAM CLI](https://github.com/awslabs/aws-sam-cli) -* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) - -## Deployment -In a shell, navigate to the sample's folder and use the SAM CLI to build a deployable package -``` -$ sam build -``` - -This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory. - -To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen - -``` -$ sam deploy --guided -``` - -Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` or a web browser to make a call to the URL - -``` -... ---------------------------------------------------------------------------------------------------------- -OutputKey-Description OutputValue ---------------------------------------------------------------------------------------------------------- -PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets ---------------------------------------------------------------------------------------------------------- - -$ curl https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets -``` \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/pom.xml b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/pom.xml deleted file mode 100644 index 84a6d5ea6..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/pom.xml +++ /dev/null @@ -1,192 +0,0 @@ - - - 4.0.0 - - oz.spring.petstore - pet-store - 1.0-SNAPSHOT - pet-store - Simple pet store written with the Spring framework - https://aws.amazon.com/lambda/ - - - https://github.com/awslabs/aws-serverless-java-container.git - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - 1.8 - 1.8 - 5.3.25 - 4.13.2 - 2.19.0 - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws-web - 3.2.9-SNAPSHOT - - - - org.springframework - spring-context-indexer - ${spring.version} - true - - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - - org.apache.logging.log4j - log4j-slf4j-impl - ${log4j.version} - - - - com.amazonaws - aws-lambda-java-log4j2 - 1.5.1 - - - - junit - junit - ${junit.version} - test - - - - - - shaded-jar - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - - package - - shade - - - false - - - - - - - - - - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.8.1 - - - - - - - - assembly-zip - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - default-jar - none - - - - - org.apache.maven.plugins - maven-install-plugin - 3.0.0-M1 - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.2.0 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - runtime - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - zip-assembly - package - - single - - - ${project.artifactId}-${project.version} - - src${file.separator}assembly${file.separator}bin.xml - - false - - - - - - - - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/assembly/bin.xml b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/assembly/bin.xml deleted file mode 100644 index 1ffd82d1c..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/assembly/bin.xml +++ /dev/null @@ -1,24 +0,0 @@ - - lambda-package - - zip - - false - - - - ${project.build.directory}${file.separator}lib - lib - - - - ${project.build.directory}${file.separator}classes - - ** - - ${file.separator} - - - \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetStoreSpringAppConfig.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetStoreSpringAppConfig.java deleted file mode 100644 index 3969ea641..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetStoreSpringAppConfig.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2023-2023 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 oz.spring.petstore; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerExceptionResolver; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - - -@Configuration -@Import({ PetsController.class }) -public class PetStoreSpringAppConfig { - /* - * Create required HandlerMapping, to avoid several default HandlerMapping instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - /* - * optimization - avoids creating default exception resolvers; not required as the serverless container handles - * all exceptions - * - * By default, an ExceptionHandlerExceptionResolver is created which creates many dependent object, including - * an expensive ObjectMapper instance. - * - * To enable custom @ControllerAdvice classes remove this bean. - */ - @Bean - public HandlerExceptionResolver handlerExceptionResolver() { - return new HandlerExceptionResolver() { - - @Override - public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { - return null; - } - }; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetsController.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetsController.java deleted file mode 100644 index b04a26d92..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/PetsController.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2023-2023 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 oz.spring.petstore; - -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -import oz.spring.petstore.model.Pet; -import oz.spring.petstore.model.PetData; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - -@RestController -@EnableWebMvc -public class PetsController { - @RequestMapping(path = "/pets", method = RequestMethod.POST) - public Pet createPet(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @RequestMapping(path = "/pets", method = RequestMethod.GET) - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @GetMapping("favicon.ico") - @ResponseBody - void returnNoFavicon() { - } - - @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET) - public Pet listPets() { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Error.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Error.java deleted file mode 100644 index bb19a9027..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Error.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2023-2023 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 oz.spring.petstore.model; - -public class Error { - private String message; - - public Error(String errorMessage) { - message = errorMessage; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Pet.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Pet.java deleted file mode 100644 index 20f170a99..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/Pet.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2023-2023 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 oz.spring.petstore.model; - -import java.util.Date; - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/PetData.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/PetData.java deleted file mode 100644 index 1df3632cc..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/src/main/java/oz/spring/petstore/model/PetData.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2023-2023 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 oz.spring.petstore.model; - -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt( - Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR) - ); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/template.yml b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/template.yml deleted file mode 100644 index 7c5cea2e3..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/sample/pet-store/template.yml +++ /dev/null @@ -1,37 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: Example Pet Store API written with spring-cloud-function web-proxy support - -Globals: - Api: - # API Gateway regional endpoints - EndpointConfiguration: REGIONAL - -Resources: - PetStoreFunction: - Type: AWS::Serverless::Function - Properties: - Handler: org.springframework.cloud.function.adapter.aws.web.WebProxyInvoker::handleRequest - Runtime: java11 - CodeUri: . - MemorySize: 512 - Policies: AWSLambdaBasicExecutionRole - Timeout: 30 - Environment: - Variables: - MAIN_CLASS: oz.spring.petstore.PetStoreSpringAppConfig - Events: - HttpApiEvent: - Type: HttpApi - Properties: - TimeoutInMillis: 20000 - PayloadFormatVersion: '1.0' - -Outputs: - SpringPetStoreApi: - Description: URL for application - Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/pets' - Export: - Name: PetStoreLambda - - diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/FunctionClassUtils.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/FunctionClassUtils.java deleted file mode 100644 index 44d6ef454..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/FunctionClassUtils.java +++ /dev/null @@ -1,145 +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.serverless.web; - -import java.io.InputStream; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.jar.JarFile; -import java.util.jar.Manifest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -//import org.springframework.boot.SpringBootConfiguration; -//import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.core.KotlinDetector; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -/** - * General utility class which aggregates various class-level utility functions - * used by the framework. - * - * @author Oleg Zhurakousky - * @since 3.0.1 - */ -public final class FunctionClassUtils { - - private static Log logger = LogFactory.getLog(FunctionClassUtils.class); - - private static Class MAIN_CLASS; - - private FunctionClassUtils() { - - } - - /** - * Discovers the start class in the currently running application. - * The discover search order is 'MAIN_CLASS' environment property, - * 'MAIN_CLASS' system property, META-INF/MANIFEST.MF:'Start-Class' attribute, - * meta-inf/manifest.mf:'Start-Class' attribute. - * - * @return instance of Class which represent the start class of the application. - */ - public static Class getStartClass() { - if (MAIN_CLASS == null) { - ClassLoader classLoader = FunctionClassUtils.class.getClassLoader(); - MAIN_CLASS = getStartClass(classLoader); - } - return MAIN_CLASS; - } - - static Class getStartClass(ClassLoader classLoader) { - Class mainClass = null; - if (System.getenv("MAIN_CLASS") != null) { - mainClass = ClassUtils.resolveClassName(System.getenv("MAIN_CLASS"), classLoader); - } - else if (System.getProperty("MAIN_CLASS") != null) { - mainClass = ClassUtils.resolveClassName(System.getProperty("MAIN_CLASS"), classLoader); - } - else { - try { - Class result = getStartClass( - Collections.list(classLoader.getResources(JarFile.MANIFEST_NAME)), classLoader); - if (result == null) { - result = getStartClass(Collections - .list(classLoader.getResources("meta-inf/manifest.mf")), classLoader); - } - Assert.notNull(result, "Failed to locate main class"); - mainClass = result; - } - catch (Exception ex) { - throw new IllegalStateException("Failed to discover main class. An attempt was made to discover " - + "main class as 'MAIN_CLASS' environment variable, system property as well as " - + "entry in META-INF/MANIFEST.MF (in that order).", ex); - } - } - logger.info("Main class: " + mainClass); - return mainClass; - } - - private static Class getStartClass(List list, ClassLoader classLoader) { - if (logger.isTraceEnabled()) { - logger.trace("Searching manifests: " + list); - } - for (URL url : list) { - try { - InputStream inputStream = null; - Manifest manifest = new Manifest(url.openStream()); - logger.info("Searching for start class in manifest: " + url); - if (logger.isDebugEnabled()) { - manifest.write(System.out); - } - try { - String startClassName = manifest.getMainAttributes().getValue("Start-Class"); - if (!StringUtils.hasText(startClassName)) { - startClassName = manifest.getMainAttributes().getValue("Main-Class"); - } - - if (StringUtils.hasText(startClassName)) { - Class startClass = ClassUtils.forName(startClassName, classLoader); - - if (KotlinDetector.isKotlinType(startClass)) { - PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver(classLoader); - String packageName = startClass.getPackage().getName(); - Resource[] resources = r.getResources("classpath:" + packageName.replace(".", "/") + "/*.class"); - for (int i = 0; i < resources.length; i++) { - Resource resource = resources[i]; - String className = packageName + "." + (resource.getFilename().replace("/", ".")).replace(".class", ""); - startClass = ClassUtils.forName(className, classLoader); - } - } - } - } - finally { - if (inputStream != null) { - inputStream.close(); - } - } - } - catch (Exception ex) { - logger.debug("Failed to determine Start-Class in manifest file of " + url, ex); - } - } - return null; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyAsyncContext.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyAsyncContext.java deleted file mode 100644 index 5078a7491..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyAsyncContext.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import jakarta.servlet.AsyncContext; -import jakarta.servlet.AsyncEvent; -import jakarta.servlet.AsyncListener; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import org.springframework.beans.BeanUtils; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.web.util.WebUtils; - -/** - * Implementation of Async context for {@link ProxyMvc}. - * - * @author Oleg Zhurakousky - */ -public class ProxyAsyncContext implements AsyncContext { - private final HttpServletRequest request; - - @Nullable - private final HttpServletResponse response; - - private final List listeners = new ArrayList<>(); - - @Nullable - private String dispatchedPath; - - private long timeout = 10 * 1000L; - - private final List dispatchHandlers = new ArrayList<>(); - - - public ProxyAsyncContext(ServletRequest request, @Nullable ServletResponse response) { - this.request = (HttpServletRequest) request; - this.response = (HttpServletResponse) response; - } - - - public void addDispatchHandler(Runnable handler) { - Assert.notNull(handler, "Dispatch handler must not be null"); - synchronized (this) { - if (this.dispatchedPath == null) { - this.dispatchHandlers.add(handler); - } - else { - handler.run(); - } - } - } - - @Override - public ServletRequest getRequest() { - return this.request; - } - - @Override - @Nullable - public ServletResponse getResponse() { - return this.response; - } - - @Override - public boolean hasOriginalRequestAndResponse() { - return (this.request instanceof ProxyHttpServletRequest && this.response instanceof ProxyHttpServletResponse); - } - - @Override - public void dispatch() { - dispatch(this.request.getRequestURI()); - } - - @Override - public void dispatch(String path) { - dispatch(null, path); - } - - @Override - public void dispatch(@Nullable ServletContext context, String path) { - synchronized (this) { - this.dispatchedPath = path; - this.dispatchHandlers.forEach(Runnable::run); - } - } - - @Nullable - public String getDispatchedPath() { - return this.dispatchedPath; - } - - @Override - public void complete() { - ProxyHttpServletRequest mockRequest = WebUtils.getNativeRequest(this.request, ProxyHttpServletRequest.class); - if (mockRequest != null) { - mockRequest.setAsyncStarted(false); - } - for (AsyncListener listener : this.listeners) { - try { - listener.onComplete(new AsyncEvent(this, this.request, this.response)); - } - catch (IOException ex) { - throw new IllegalStateException("AsyncListener failure", ex); - } - } - } - - @Override - public void start(Runnable runnable) { - runnable.run(); - } - - @Override - public void addListener(AsyncListener listener) { - this.listeners.add(listener); - } - - @Override - public void addListener(AsyncListener listener, ServletRequest request, ServletResponse response) { - this.listeners.add(listener); - } - - public List getListeners() { - return this.listeners; - } - - @Override - public T createListener(Class clazz) throws ServletException { - return BeanUtils.instantiateClass(clazz); - } - - /** - * By default this is set to 10000 (10 seconds) even though the Servlet API - * specifies a default async request timeout of 30 seconds. Keep in mind the - * timeout could further be impacted by global configuration through the MVC - * Java config or the XML namespace, as well as be overridden per request on - * {@link org.springframework.web.context.request.async.DeferredResult DeferredResult} - * or on - * {@link org.springframework.web.servlet.mvc.method.annotation.SseEmitter SseEmitter}. - * @param timeout the timeout value to use. - * @see AsyncContext#setTimeout(long) - */ - @Override - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - @Override - public long getTimeout() { - return this.timeout; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyErrorController.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyErrorController.java deleted file mode 100644 index a3de30931..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyErrorController.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.view.json.MappingJackson2JsonView; - -/** - * - * @author Oleg Zhurakousky - * - */ -@Controller -@RequestMapping("/error") -public class ProxyErrorController { - - private final SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z"); - - private final MappingJackson2JsonView view = new MappingJackson2JsonView(); - - @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) - public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { - HttpStatus status = getStatus(request); - Map model = new HashMap<>(); - model.put("status", response.getStatus()); - model.put("error", request.getAttribute(RequestDispatcher.ERROR_MESSAGE)); - model.put("path", request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI)); - model.put("timestamp", df.format(new Date())); - response.setStatus(status.value()); - ModelAndView modelAndView = resolveErrorView(request, response, status, model); - return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); - } - - protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, - Map model) { - ModelAndView modelAndView = new ModelAndView("Whitelabel Error Page", model); - modelAndView.setStatus(status); - modelAndView.setView(this.view); - return modelAndView; - } - - protected HttpStatus getStatus(HttpServletRequest request) { - Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); - if (statusCode == null) { - return HttpStatus.INTERNAL_SERVER_ERROR; - } - try { - return HttpStatus.valueOf(statusCode); - } - catch (Exception ex) { - return HttpStatus.INTERNAL_SERVER_ERROR; - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyFilterRegistration.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyFilterRegistration.java deleted file mode 100644 index 43e20212f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyFilterRegistration.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.util.Collection; -import java.util.EnumSet; -import java.util.Map; -import java.util.Set; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.Filter; -import jakarta.servlet.FilterRegistration; - -/** - * - * @author Oleg Zhurakousky - * @since 4.x - * - */ -public class ProxyFilterRegistration implements FilterRegistration, FilterRegistration.Dynamic { - - public Filter getFilter() { - return filter; - } - - private final String name; - - private final Filter filter; - - public ProxyFilterRegistration(String name, Filter filter) { - this.name = name; - this.filter = filter; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getClassName() { - return this.filter.getClass().getName(); - } - - @Override - public boolean setInitParameter(String name, String value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getInitParameter(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Set setInitParameters(Map initParameters) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getInitParameters() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setAsyncSupported(boolean isAsyncSupported) { - // TODO Auto-generated method stub - - } - - @Override - public void addMappingForServletNames(EnumSet dispatcherTypes, boolean isMatchAfter, - String... servletNames) { - // TODO Auto-generated method stub - - } - - @Override - public Collection getServletNameMappings() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void addMappingForUrlPatterns(EnumSet dispatcherTypes, boolean isMatchAfter, - String... urlPatterns) { - // TODO Auto-generated method stub - - } - - @Override - public Collection getUrlPatternMappings() { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletRequest.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletRequest.java deleted file mode 100644 index 3be55e479..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletRequest.java +++ /dev/null @@ -1,1013 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.security.Principal; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; - -import jakarta.servlet.AsyncContext; -import jakarta.servlet.DispatcherType; -import jakarta.servlet.ReadListener; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.ServletConnection; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; -import jakarta.servlet.http.HttpUpgradeHandler; -import jakarta.servlet.http.Part; - -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class ProxyHttpServletRequest implements HttpServletRequest { - - private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); - - private static final BufferedReader EMPTY_BUFFERED_READER = new BufferedReader(new StringReader("")); - - /** - * Date formats as specified in the HTTP RFC. - * - * @see Section - * 7.1.1.1 of RFC 7231 - */ - private static final String[] DATE_FORMATS = new String[] { "EEE, dd MMM yyyy HH:mm:ss zzz", - "EEE, dd-MMM-yy HH:mm:ss zzz", "EEE MMM dd HH:mm:ss yyyy" }; - - private final ServletContext servletContext; - - // --------------------------------------------------------------------- - // ServletRequest properties - // --------------------------------------------------------------------- - - private final Map attributes = new LinkedHashMap<>(); - - @Nullable - private String characterEncoding; - - @Nullable - private byte[] content; - - @Nullable - private ServletInputStream inputStream; - - @Nullable - private BufferedReader reader; - - private final Map parameters = new LinkedHashMap<>(16); - - /** List of locales in descending order. */ - private final LinkedList locales = new LinkedList<>(); - - private boolean asyncStarted = false; - - private boolean asyncSupported = true; - - private DispatcherType dispatcherType = DispatcherType.REQUEST; - - @Nullable - private String authType; - - @Nullable - private Cookie[] cookies; - - private final HttpHeaders headers = new HttpHeaders(); - - @Nullable - private String method; - - @Nullable - private String pathInfo; - - private String contextPath = ""; - - @Nullable - private String queryString; - - @Nullable - private String remoteUser; - - private final Set userRoles = new HashSet<>(); - - @Nullable - private Principal userPrincipal; - - @Nullable - private String requestedSessionId; - - @Nullable - private String requestURI; - - private String servletPath = ""; - - @Nullable - private HttpSession session; - - private boolean requestedSessionIdValid = true; - - private boolean requestedSessionIdFromCookie = true; - - private boolean requestedSessionIdFromURL = false; - - private final MultiValueMap parts = new LinkedMultiValueMap<>(); - - private AsyncContext asyncContext; - - public ProxyHttpServletRequest(ServletContext servletContext, String method, String requestURI) { - this.servletContext = servletContext; - this.method = method; - this.requestURI = requestURI; - this.locales.add(Locale.ENGLISH); - } - - /** - * Return the ServletContext that this request is associated with. (Not - * available in the standard HttpServletRequest interface for some reason.) - */ - @Override - public ServletContext getServletContext() { - return this.servletContext; - } - - @Override - public Object getAttribute(String name) { - return this.attributes.get(name); - } - - @Override - public Enumeration getAttributeNames() { - return Collections.enumeration(new LinkedHashSet<>(this.attributes.keySet())); - } - - @Override - @Nullable - public String getCharacterEncoding() { - return this.characterEncoding; - } - - @Override - public void setCharacterEncoding(@Nullable String characterEncoding) { - this.characterEncoding = characterEncoding; - } - - /** - * Set the content of the request body as a byte array. - *

- * If the supplied byte array represents text such as XML or JSON, the - * {@link #setCharacterEncoding character encoding} should typically be set as - * well. - * - * @see #setCharacterEncoding(String) - * @see #getContentAsByteArray() - * @see #getContentAsString() - */ - public void setContent(@Nullable byte[] content) { - this.content = content; - this.inputStream = null; - this.reader = null; - } - - /** - * Get the content of the request body as a byte array. - * - * @return the content as a byte array (potentially {@code null}) - * @since 5.0 - * @see #setContent(byte[]) - * @see #getContentAsString() - */ - @Nullable - public byte[] getContentAsByteArray() { - return this.content; - } - - /** - * Get the content of the request body as a {@code String}, using the configured - * {@linkplain #getCharacterEncoding character encoding}. - * - * @return the content as a {@code String}, potentially {@code null} - * @throws IllegalStateException if the character encoding has not been - * set - * @throws UnsupportedEncodingException if the character encoding is not - * supported - * @since 5.0 - * @see #setContent(byte[]) - * @see #setCharacterEncoding(String) - * @see #getContentAsByteArray() - */ - @Nullable - public String getContentAsString() throws IllegalStateException, UnsupportedEncodingException { - - if (this.content == null) { - return null; - } - return new String(this.content, StandardCharsets.UTF_8); - } - - @Override - public int getContentLength() { - return (this.content != null ? this.content.length : -1); - } - - @Override - public long getContentLengthLong() { - return getContentLength(); - } - - public void setContentType(@Nullable String contentType) { - this.headers.set(HttpHeaders.CONTENT_TYPE, contentType); - } - - @Override - @Nullable - public String getContentType() { - return this.headers.containsKey(HttpHeaders.CONTENT_TYPE) ? this.headers.get(HttpHeaders.CONTENT_TYPE).get(0) : null; - } - - @Override - public ServletInputStream getInputStream() { - InputStream stream = new ByteArrayInputStream(this.content); - return new ServletInputStream() { - - boolean finished = false; - - @Override - public int read() throws IOException { - int readByte = stream.read(); - if (readByte == -1) { - finished = true; - } - return readByte; - } - - @Override - public void setReadListener(ReadListener readListener) { - } - - @Override - public boolean isReady() { - return !finished; - } - - @Override - public boolean isFinished() { - return finished; - } - }; - } - - /** - * Set a single value for the specified HTTP parameter. - *

- * If there are already one or more values registered for the given parameter - * name, they will be replaced. - */ - public void setParameter(String name, String value) { - setParameter(name, new String[] { value }); - } - - /** - * Set an array of values for the specified HTTP parameter. - *

- * If there are already one or more values registered for the given parameter - * name, they will be replaced. - */ - public void setParameter(String name, String... values) { - Assert.notNull(name, "Parameter name must not be null"); - this.parameters.put(name, values); - } - - /** - * Set all provided parameters replacing any existing values - * for the provided parameter names. To add without replacing existing values, - * use {@link #addParameters(java.util.Map)}. - */ - public void setParameters(Map params) { - Assert.notNull(params, "Parameter map must not be null"); - params.forEach((key, value) -> { - if (value instanceof String) { - setParameter(key, (String) value); - } - else if (value instanceof String[]) { - setParameter(key, (String[]) value); - } - else { - throw new IllegalArgumentException("Parameter map value must be single value " + " or array of type [" - + String.class.getName() + "]"); - } - }); - } - - /** - * Add a single value for the specified HTTP parameter. - *

- * If there are already one or more values registered for the given parameter - * name, the given value will be added to the end of the list. - */ - public void addParameter(String name, @Nullable String value) { - addParameter(name, new String[] { value }); - } - - /** - * Add an array of values for the specified HTTP parameter. - *

- * If there are already one or more values registered for the given parameter - * name, the given values will be added to the end of the list. - */ - public void addParameter(String name, String... values) { - Assert.notNull(name, "Parameter name must not be null"); - String[] oldArr = this.parameters.get(name); - if (oldArr != null) { - String[] newArr = new String[oldArr.length + values.length]; - System.arraycopy(oldArr, 0, newArr, 0, oldArr.length); - System.arraycopy(values, 0, newArr, oldArr.length, values.length); - this.parameters.put(name, newArr); - } - else { - this.parameters.put(name, values); - } - } - - /** - * Add all provided parameters without replacing any existing - * values. To replace existing values, use - * {@link #setParameters(java.util.Map)}. - */ - public void addParameters(Map params) { - Assert.notNull(params, "Parameter map must not be null"); - params.forEach((key, value) -> { - if (value instanceof String) { - addParameter(key, (String) value); - } - else if (value instanceof String[]) { - addParameter(key, (String[]) value); - } - else { - throw new IllegalArgumentException("Parameter map value must be single value " + " or array of type [" - + String.class.getName() + "]"); - } - }); - } - - /** - * Remove already registered values for the specified HTTP parameter, if any. - */ - public void removeParameter(String name) { - Assert.notNull(name, "Parameter name must not be null"); - this.parameters.remove(name); - } - - /** - * Remove all existing parameters. - */ - public void removeAllParameters() { - this.parameters.clear(); - } - - @Override - @Nullable - public String getParameter(String name) { - Assert.notNull(name, "Parameter name must not be null"); - String[] arr = this.parameters.get(name); - return (arr != null && arr.length > 0 ? arr[0] : null); - } - - @Override - public Enumeration getParameterNames() { - return Collections.enumeration(this.parameters.keySet()); - } - - @Override - public String[] getParameterValues(String name) { - Assert.notNull(name, "Parameter name must not be null"); - return this.parameters.get(name); - } - - @Override - public Map getParameterMap() { - return Collections.unmodifiableMap(this.parameters); - } - - @Override - public String getProtocol() { - throw new UnsupportedOperationException(); - } - - @Override - public String getScheme() { - return "https"; - } - - public void setServerName(String serverName) { - throw new UnsupportedOperationException(); - } - - @Override - public String getServerName() { - return "spring-serverless-web-proxy"; - } - - public void setServerPort(int serverPort) { - throw new UnsupportedOperationException(); - } - - @Override - public int getServerPort() { - return 0; - } - - @Override - public BufferedReader getReader() throws UnsupportedEncodingException { - if (this.reader != null) { - return this.reader; - } - else if (this.inputStream != null) { - throw new IllegalStateException( - "Cannot call getReader() after getInputStream() has already been called for the current request"); - } - - if (this.content != null) { - InputStream sourceStream = new ByteArrayInputStream(this.content); - Reader sourceReader = (this.characterEncoding != null) - ? new InputStreamReader(sourceStream, this.characterEncoding) - : new InputStreamReader(sourceStream); - this.reader = new BufferedReader(sourceReader); - } - else { - this.reader = EMPTY_BUFFERED_READER; - } - return this.reader; - } - - public void setRemoteAddr(String remoteAddr) { - throw new UnsupportedOperationException(); - } - - @Override - public String getRemoteAddr() { - return "proxy"; - } - - public void setRemoteHost(String remoteHost) { - throw new UnsupportedOperationException(); - } - - @Override - public String getRemoteHost() { - throw new UnsupportedOperationException(); - } - - @Override - public void setAttribute(String name, @Nullable Object value) { - Assert.notNull(name, "Attribute name must not be null"); - if (value != null) { - this.attributes.put(name, value); - } - else { - this.attributes.remove(name); - } - } - - @Override - public void removeAttribute(String name) { - Assert.notNull(name, "Attribute name must not be null"); - this.attributes.remove(name); - } - - /** - * Clear all of this request's attributes. - */ - public void clearAttributes() { - this.attributes.clear(); - } - - /** - * Return the first preferred {@linkplain Locale locale} configured in this mock - * request. - *

- * If no locales have been explicitly configured, the default, preferred - * {@link Locale} for the server mocked by this request is - * {@link Locale#ENGLISH}. - *

- * In contrast to the Servlet specification, this mock implementation does - * not take into consideration any locales specified via the - * {@code Accept-Language} header. - * - * @see javax.servlet.ServletRequest#getLocale() - * @see #addPreferredLocale(Locale) - * @see #setPreferredLocales(List) - */ - @Override - public Locale getLocale() { - return this.locales.getFirst(); - } - - /** - * Return an {@linkplain Enumeration enumeration} of the preferred - * {@linkplain Locale locales} configured in this mock request. - *

- * If no locales have been explicitly configured, the default, preferred - * {@link Locale} for the server mocked by this request is - * {@link Locale#ENGLISH}. - *

- * In contrast to the Servlet specification, this mock implementation does - * not take into consideration any locales specified via the - * {@code Accept-Language} header. - * - * @see javax.servlet.ServletRequest#getLocales() - * @see #addPreferredLocale(Locale) - * @see #setPreferredLocales(List) - */ - @Override - public Enumeration getLocales() { - return Collections.enumeration(this.locales); - } - - /** - * Return {@code true} if the {@link #setSecure secure} flag has been set to - * {@code true} or if the {@link #getScheme scheme} is {@code https}. - * - * @see javax.servlet.ServletRequest#isSecure() - */ - @Override - public boolean isSecure() { - return false; - } - - @Override - public RequestDispatcher getRequestDispatcher(String path) { - throw new UnsupportedOperationException(); - } - - public void setRemotePort(int remotePort) { - throw new UnsupportedOperationException(); - } - - @Override - public int getRemotePort() { - throw new UnsupportedOperationException(); - } - - public void setLocalName(String localName) { - throw new UnsupportedOperationException(); - } - - @Override - public String getLocalName() { - throw new UnsupportedOperationException(); - } - - public void setLocalAddr(String localAddr) { - throw new UnsupportedOperationException(); - } - - @Override - public String getLocalAddr() { - return "proxy"; - } - - public void setLocalPort(int localPort) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLocalPort() { - throw new UnsupportedOperationException(); - } - - @Override - public AsyncContext startAsync() { - return startAsync(this, null); - } - - @Override - public AsyncContext startAsync(ServletRequest request, @Nullable ServletResponse response) { - Assert.state(this.asyncSupported, "Async not supported"); - this.dispatcherType = DispatcherType.ASYNC; - this.asyncStarted = true; - this.asyncContext = this.asyncContext == null ? new ProxyAsyncContext(request, response) : this.asyncContext; - return this.asyncContext; - } - - public void setAsyncStarted(boolean asyncStarted) { - this.asyncStarted = asyncStarted; - } - - @Override - public boolean isAsyncStarted() { - return this.asyncStarted; - } - - public void setAsyncSupported(boolean asyncSupported) { - this.asyncSupported = asyncSupported; - this.dispatcherType = DispatcherType.ASYNC; - } - - @Override - public boolean isAsyncSupported() { - return this.asyncSupported; - } - - public void setAsyncContext(@Nullable AsyncContext asyncContext) { - this.asyncContext = asyncContext; - } - - @Override - @Nullable - public AsyncContext getAsyncContext() { - return this.asyncContext; - } - - - public void setDispatcherType(DispatcherType dispatcherType) { - this.dispatcherType = dispatcherType; - } - - @Override - public DispatcherType getDispatcherType() { - return this.dispatcherType; - } - - public void setAuthType(@Nullable String authType) { - this.authType = authType; - } - - @Override - @Nullable - public String getAuthType() { - return this.authType; - } - - @Override - @Nullable - public Cookie[] getCookies() { - return this.cookies; - } - - @Override - @Nullable - public String getHeader(String name) { - return this.headers.containsKey(name) ? this.headers.get(name).get(0) : null; - } - - @Override - public Enumeration getHeaders(String name) { - return Collections.enumeration(this.headers.containsKey(name) ? this.headers.get(name) : new LinkedList<>()); - } - - @Override - public Enumeration getHeaderNames() { - return Collections.enumeration(this.headers.keySet()); - } - - public void setHeader(String name, @Nullable String value) { - this.headers.set(name, value); - } - - public void addHeader(String name, @Nullable String value) { - this.headers.add(name, value); - } - - public void addHeaders(MultiValueMap headers) { - this.headers.addAll(headers); - } - - public void setHeaders(MultiValueMap headers) { - this.headers.clear(); - this.addHeaders(headers); - } - - @Override - public int getIntHeader(String name) { - List header = this.headers.get(name); - if (!CollectionUtils.isEmpty(header) && header.size() == 1) { - Object value = header.get(0); - if (value instanceof Number) { - return ((Number) value).intValue(); - } - else if (value instanceof String) { - return Integer.parseInt((String) value); - } - else if (value != null) { - throw new NumberFormatException("Value for header '" + name + "' is not a Number: " + value); - } - else { - return -1; - } - } - else { - return -1; - } - } - - @Override - public long getDateHeader(String name) { - List header = this.headers.get(name); - if (!CollectionUtils.isEmpty(header) && header.size() == 1) { - Object value = header.get(0); - if (value instanceof Date) { - return ((Date) value).getTime(); - } - else if (value instanceof Number) { - return ((Number) value).longValue(); - } - else if (value instanceof String) { - return parseDateHeader(name, (String) value); - } - else if (value != null) { - throw new IllegalArgumentException( - "Value for header '" + name + "' is not a Date, Number, or String: " + value); - } - else { - return -1L; - } - } - else { - return -1; - } - } - - private long parseDateHeader(String name, String value) { - for (String dateFormat : DATE_FORMATS) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat, Locale.US); - simpleDateFormat.setTimeZone(GMT); - try { - return simpleDateFormat.parse(value).getTime(); - } - catch (ParseException ex) { - // ignore - } - } - throw new IllegalArgumentException("Cannot parse date value '" + value + "' for '" + name + "' header"); - } - - public void setMethod(@Nullable String method) { - this.method = method; - } - - @Override - @Nullable - public String getMethod() { - return this.method; - } - - public void setPathInfo(@Nullable String pathInfo) { - this.pathInfo = pathInfo; - } - - @Override - @Nullable - public String getPathInfo() { - return this.pathInfo; - } - - @Override - @Nullable - public String getPathTranslated() { - //return (this.pathInfo != null ? getRealPath(this.pathInfo) : null); - return this.pathInfo; - } - - public void setContextPath(String contextPath) { - this.contextPath = contextPath; - } - - @Override - public String getContextPath() { - return this.contextPath; - } - - public void setQueryString(@Nullable String queryString) { - this.queryString = queryString; - } - - @Override - @Nullable - public String getQueryString() { - return this.queryString; - } - - public void setRemoteUser(@Nullable String remoteUser) { - this.remoteUser = remoteUser; - } - - @Override - @Nullable - public String getRemoteUser() { - return this.remoteUser; - } - - public void addUserRole(String role) { - this.userRoles.add(role); - } - - @Override - public boolean isUserInRole(String role) { - throw new UnsupportedOperationException(); - } - - public void setUserPrincipal(@Nullable Principal userPrincipal) { - this.userPrincipal = userPrincipal; - } - - @Override - @Nullable - public Principal getUserPrincipal() { - return this.userPrincipal; - } - - public void setRequestedSessionId(@Nullable String requestedSessionId) { - this.requestedSessionId = requestedSessionId; - } - - @Override - @Nullable - public String getRequestedSessionId() { - return this.requestedSessionId; - } - - public void setRequestURI(@Nullable String requestURI) { - this.requestURI = requestURI; - } - - @Override - @Nullable - public String getRequestURI() { - return this.requestURI; - } - - @Override - public StringBuffer getRequestURL() { - return new StringBuffer(this.requestURI); - } - - public void setServletPath(String servletPath) { - this.servletPath = servletPath; - } - - @Override - public String getServletPath() { - return this.servletPath; - } - - public void setSession(HttpSession session) { - throw new UnsupportedOperationException(); - } - - @Override - @Nullable - public HttpSession getSession(boolean create) { - if (this.session == null) { - this.session = new ProxyHttpSession(this.servletContext); - } - return this.session; - } - - @Override - @Nullable - public HttpSession getSession() { - return getSession(true); - } - - @Override - public String changeSessionId() { - throw new UnsupportedOperationException(); - } - - public void setRequestedSessionIdValid(boolean requestedSessionIdValid) { - this.requestedSessionIdValid = requestedSessionIdValid; - } - - @Override - public boolean isRequestedSessionIdValid() { - return this.requestedSessionIdValid; - } - - public void setRequestedSessionIdFromCookie(boolean requestedSessionIdFromCookie) { - this.requestedSessionIdFromCookie = requestedSessionIdFromCookie; - } - - @Override - public boolean isRequestedSessionIdFromCookie() { - return this.requestedSessionIdFromCookie; - } - - public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL) { - this.requestedSessionIdFromURL = requestedSessionIdFromURL; - } - - @Override - public boolean isRequestedSessionIdFromURL() { - return this.requestedSessionIdFromURL; - } - - @Override - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - throw new UnsupportedOperationException(); - } - - @Override - public void login(String username, String password) throws ServletException { - throw new UnsupportedOperationException(); - } - - @Override - public void logout() throws ServletException { - this.userPrincipal = null; - this.remoteUser = null; - this.authType = null; - } - - public void addPart(Part part) { - this.parts.add(part.getName(), part); - } - - @Override - @Nullable - public Part getPart(String name) throws IOException, ServletException { - return this.parts.getFirst(name); - } - - @Override - public Collection getParts() throws IOException, ServletException { - List result = new LinkedList<>(); - for (List list : this.parts.values()) { - result.addAll(list); - } - return result; - } - - @Override - public T upgrade(Class handlerClass) throws IOException, ServletException { - throw new UnsupportedOperationException(); - } - - @Override - public String getRequestId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getProtocolRequestId() { - // TODO Auto-generated method stub - return null; - } - - @Override - public ServletConnection getServletConnection() { - // TODO Auto-generated method stub - return null; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletResponse.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletResponse.java deleted file mode 100644 index 12575af1d..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpServletResponse.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.WriteListener; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletResponse; - -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.web.util.WebUtils; - - -/** - * - * @author Oleg Zhurakousky - * @since 4.x - * - */ -public class ProxyHttpServletResponse implements HttpServletResponse { - - private static final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz"; - - private String defaultCharacterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; - - private String characterEncoding = this.defaultCharacterEncoding; - - private final ByteArrayOutputStream content = new ByteArrayOutputStream(1024); - - private final ServletOutputStream outputStream = new ResponseServletOutputStream(); - - private String contentType; - - private int bufferSize = 4096; - - private Locale locale = Locale.getDefault(); - - private final List cookies = new ArrayList<>(); - - private final HttpHeaders headers = new HttpHeaders(); - - private int status = HttpServletResponse.SC_OK; - - private ResponsePrintWriter writer; - - @Nullable - private String errorMessage; - - @Override - public void setCharacterEncoding(String characterEncoding) { - this.characterEncoding = characterEncoding; - } - - @Override - public String getCharacterEncoding() { - return this.characterEncoding; - } - - @Override - public ServletOutputStream getOutputStream() { - return this.outputStream; - } - - @Override - public PrintWriter getWriter() throws UnsupportedEncodingException { - if (this.writer == null) { - Writer targetWriter = new OutputStreamWriter(this.content, getCharacterEncoding()); - this.writer = new ResponsePrintWriter(targetWriter); - } - return this.writer; - } - - public byte[] getContentAsByteArray() { - return this.content.toByteArray(); - } - - /** - * Get the content of the response body as a {@code String}, using the charset - * specified for the response by the application, either through - * {@link HttpServletResponse} methods or through a charset parameter on the - * {@code Content-Type}. If no charset has been explicitly defined, the - * {@linkplain #setDefaultCharacterEncoding(String) default character encoding} - * will be used. - * - * @return the content as a {@code String} - * @throws UnsupportedEncodingException if the character encoding is not - * supported - * @see #getContentAsString(Charset) - * @see #setCharacterEncoding(String) - * @see #setContentType(String) - */ - public String getContentAsString() throws UnsupportedEncodingException { - return this.content.toString(getCharacterEncoding()); - } - - public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException { - return this.content.toString(getCharacterEncoding()); - } - - @Override - public void setContentLength(int contentLength) { - throw new UnsupportedOperationException(); - } - - @Override - public void setContentLengthLong(long len) { - // Ignore - } - - @Override - public void setContentType(@Nullable String contentType) { - this.contentType = contentType; - } - - @Override - @Nullable - public String getContentType() { - return this.contentType; - } - - @Override - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - @Override - public int getBufferSize() { - return this.bufferSize; - } - - @Override - public void flushBuffer() { - } - - @Override - public void resetBuffer() { - Assert.state(!isCommitted(), "Cannot reset buffer - response is already committed"); - this.content.reset(); - } - - @Override - public boolean isCommitted() { - return this.writer == null ? false : this.writer.commited; - } - - @Override - public void reset() { - resetBuffer(); - this.characterEncoding = this.defaultCharacterEncoding; - this.contentType = null; - this.locale = Locale.getDefault(); - this.cookies.clear(); - this.headers.clear(); - this.status = HttpServletResponse.SC_OK; - this.errorMessage = null; - } - - @Override - public void setLocale(@Nullable Locale locale) { - if (locale == null) { - return; - } - this.locale = locale; - this.headers.add(HttpHeaders.CONTENT_LANGUAGE, locale.toLanguageTag()); - } - - @Override - public Locale getLocale() { - return this.locale; - } - - // --------------------------------------------------------------------- - // HttpServletResponse interface - // --------------------------------------------------------------------- - - @Override - public void addCookie(Cookie cookie) { - throw new UnsupportedOperationException(); - } - - @Nullable - public Cookie getCookie(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsHeader(String name) { - return this.headers.containsKey(name); - } - - /** - * Return the names of all specified headers as a Set of Strings. - *

- * As of Servlet 3.0, this method is also defined in - * {@link HttpServletResponse}. - * - * @return the {@code Set} of header name {@code Strings}, or an empty - * {@code Set} if none - */ - @Override - public Collection getHeaderNames() { - return this.headers.keySet(); - } - - /** - * Return the primary value for the given header as a String, if any. Will - * return the first value in case of multiple values. - *

- * As of Servlet 3.0, this method is also defined in - * {@link HttpServletResponse}. As of Spring 3.1, it returns a stringified value - * for Servlet 3.0 compatibility. Consider using {@link #getHeaderValue(String)} - * for raw Object access. - * - * @param name the name of the header - * @return the associated header value, or {@code null} if none - */ - @Override - @Nullable - public String getHeader(String name) { - return this.headers.containsKey(name) ? this.headers.get(name).get(0) : null; - } - - /** - * Return all values for the given header as a List of Strings. - *

- * As of Servlet 3.0, this method is also defined in - * {@link HttpServletResponse}. As of Spring 3.1, it returns a List of - * stringified values for Servlet 3.0 compatibility. Consider using - * {@link #getHeaderValues(String)} for raw Object access. - * - * @param name the name of the header - * @return the associated header values, or an empty List if none - */ - @Override - public List getHeaders(String name) { - if (!this.headers.containsKey(name)) { - return Collections.emptyList(); - } - return this.headers.get(name); - } - - /** - * Return the primary value for the given header, if any. - *

- * Will return the first value in case of multiple values. - * - * @param name the name of the header - * @return the associated header value, or {@code null} if none - */ - @Nullable - public Object getHeaderValue(String name) { - return this.headers.containsKey(name) ? this.headers.get(name).get(0) : null; - } - - /** - * The default implementation returns the given URL String as-is. - *

- * Can be overridden in subclasses, appending a session id or the like. - */ - @Override - public String encodeURL(String url) { - return url; - } - - /** - * The default implementation delegates to {@link #encodeURL}, returning the - * given URL String as-is. - *

- * Can be overridden in subclasses, appending a session id or the like in a - * redirect-specific fashion. For general URL encoding rules, override the - * common {@link #encodeURL} method instead, applying to redirect URLs as well - * as to general URLs. - */ - @Override - public String encodeRedirectURL(String url) { - return encodeURL(url); - } - - @Override - public void sendError(int status, String errorMessage) throws IOException { - Assert.state(!isCommitted(), "Cannot set error status - response is already committed"); - this.status = status; - this.errorMessage = errorMessage; - } - - @Override - public void sendError(int status) throws IOException { - Assert.state(!isCommitted(), "Cannot set error status - response is already committed"); - this.status = status; - } - - @Override - public void sendRedirect(String url) throws IOException { - Assert.state(!isCommitted(), "Cannot send redirect - response is already committed"); - Assert.notNull(url, "Redirect URL must not be null"); - setHeader(HttpHeaders.LOCATION, url); - setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); - } - - @Nullable - public String getRedirectedUrl() { - return getHeader(HttpHeaders.LOCATION); - } - - @Override - public void setDateHeader(String name, long value) { - this.headers.set(name, formatDate(value)); - } - - @Override - public void addDateHeader(String name, long value) { - this.headers.add(name, formatDate(value)); - } - - private String formatDate(long date) { - return newDateFormat().format(new Date(date)); - } - - private DateFormat newDateFormat() { - SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); - return dateFormat; - } - - @Override - public void setHeader(String name, @Nullable String value) { - this.headers.set(name, value); - } - - @Override - public void addHeader(String name, @Nullable String value) { - this.headers.add(name, value); - } - - @Override - public void setIntHeader(String name, int value) { - this.headers.set(name, String.valueOf(value)); - } - - @Override - public void addIntHeader(String name, int value) { - this.headers.add(name, String.valueOf(value)); - } - - @Override - public void setStatus(int status) { - if (!this.isCommitted()) { - this.status = status; - } - } - - - @Override - public int getStatus() { - return this.status; - } - - @Nullable - public String getErrorMessage() { - return this.errorMessage; - } - - /** - * Inner class that adapts the ServletOutputStream to mark the response as - * committed once the buffer size is exceeded. - */ - private class ResponseServletOutputStream extends ServletOutputStream { - - private WriteListener listener; - - @Override - public boolean isReady() { - return true; - } - - @Override - public void setWriteListener(WriteListener writeListener) { - if (writeListener != null) { - try { - writeListener.onWritePossible(); - } - catch (IOException e) { - // log.error("Output stream is not writable", e); - } - - listener = writeListener; - } - } - - @Override - public void write(int b) throws IOException { - try { - content.write(b); - } - catch (Exception e) { - if (listener != null) { - listener.onError(e); - } - } - } - - @Override - public void close() throws IOException { - super.close(); - flushBuffer(); - } - } - - private class ResponsePrintWriter extends PrintWriter { - - private boolean commited; - - ResponsePrintWriter(Writer out) { - super(out, true); - } - - @Override - public void write(char[] buf, int off, int len) { - super.write(buf, off, len); - super.flush(); - this.commited = true; - } - - @Override - public void write(String s, int off, int len) { - super.write(s, off, len); - super.flush(); - this.commited = true; - } - - @Override - public void write(int c) { - super.write(c); - super.flush(); - this.commited = true; - } - - @Override - public void flush() { - super.flush(); - this.commited = true; - } - - @Override - public void close() { - super.flush(); - super.close(); - this.commited = true; - } - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpSession.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpSession.java deleted file mode 100644 index 0e41f4836..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyHttpSession.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.HttpSession; - -/** - * - * @author Oleg Zhurakousky - * @since 4.x - * - * - */ -public class ProxyHttpSession implements HttpSession { - - private final long creationTime; - - private final String sessionId; - - private final ServletContext servletContext; - - private final Map attributes = new HashMap<>(); - - public ProxyHttpSession(ServletContext servletContext) { - this.creationTime = new Date().getTime(); - this.sessionId = UUID.randomUUID().toString(); - this.servletContext = servletContext; - } - - @Override - public long getCreationTime() { - return this.creationTime; - } - - @Override - public String getId() { - return this.sessionId; - } - - @Override - public long getLastAccessedTime() { - return 0; - } - - @Override - public ServletContext getServletContext() { - return this.servletContext; - } - - @Override - public void setMaxInactiveInterval(int interval) { - - } - - @Override - public int getMaxInactiveInterval() { - return 0; - } - - @Override - public Object getAttribute(String name) { - return this.attributes.get(name); - } - - @Override - public Enumeration getAttributeNames() { - return Collections.enumeration(this.attributes.keySet()); - } - - @Override - public void setAttribute(String name, Object value) { - this.attributes.put(name, value); - } - - @Override - public void removeAttribute(String name) { - this.attributes.remove(name); - } - - @Override - public void invalidate() { - - } - - @Override - public boolean isNew() { - return false; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyMvc.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyMvc.java deleted file mode 100644 index 397daaced..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyMvc.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import jakarta.servlet.AsyncContext; -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.http.HttpStatus; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; -import org.springframework.web.context.ConfigurableWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -/** - * Represents the main entry point into interaction with web application over light-weight proxy. - * After creating an instance via {@link #INSTANCE(Class...)} operation which will initialize the provided component - * classes of your web application (effectively starting your web application less web server), - * you use {@link #service(HttpServletRequest, HttpServletResponse)} operation to send request and receive a response. - * - * @author Oleg Zhurakousky - * - */ -public final class ProxyMvc { - - private static Log LOG = LogFactory.getLog(ProxyMvc.class); - - private final DispatcherServlet dispatcher; - - private final ConfigurableWebApplicationContext applicationContext; - - private ServletContext servletContext; - - public ConfigurableWebApplicationContext getApplicationContext() { - return this.applicationContext; - } - - public ServletContext getServletContext() { - return this.servletContext; - } - - public static ProxyMvc INSTANCE(ConfigurableWebApplicationContext applpicationContext) { - return new ProxyMvc(applpicationContext); - } - - public static ProxyMvc INSTANCE(Class... componentClasses) { - ConfigurableWebApplicationContext applpicationContext = ServerlessWebApplication.run(componentClasses, new String[] {}); - return INSTANCE(applpicationContext); - } - - - /** - * Private constructor, not for direct instantiation. - */ - ProxyMvc(ConfigurableWebApplicationContext applicationContext) { - this.applicationContext = applicationContext; - ProxyServletContext servletContext = new ProxyServletContext(); - this.applicationContext.setServletContext(servletContext); - this.applicationContext.refresh(); - - if (this.applicationContext.containsBean(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) { - this.dispatcher = this.applicationContext.getBean(DispatcherServlet.class); - } - else { - this.dispatcher = new DispatcherServlet(this.applicationContext); - this.dispatcher.setDetectAllHandlerMappings(false); - ((GenericApplicationContext) this.applicationContext).registerBean(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME, - DispatcherServlet.class, () -> this.dispatcher); - } - - ServletRegistration.Dynamic reg = servletContext.addServlet(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME, dispatcher); - reg.setLoadOnStartup(1); - this.servletContext = applicationContext.getServletContext(); - try { - this.dispatcher.init(new ProxyServletConfig(this.servletContext)); - } - catch (Exception e) { - throw new IllegalStateException("Faild to create Spring MVC DispatcherServlet proxy", e); - } - } - - public void stop() { - this.applicationContext.stop(); - } - - /** - * Perform a request and return a type that allows chaining further actions, - * such as asserting expectations, on the result. - * - * @param requestBuilder used to prepare the request to execute; see static - * factory methods in - * {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders} - * @return an instance of {@link ResultActions} (never {@code null}) - * @see org.springframework.test.web.servlet.request.MockMvcRequestBuilders - * @see org.springframework.test.web.servlet.result.MockMvcResultMatchers - */ - public void service(HttpServletRequest request, HttpServletResponse response) throws Exception { - this.service(request, response, (CountDownLatch) null); - } - - - public void service(HttpServletRequest request, HttpServletResponse response, CountDownLatch latch) throws Exception { - ProxyFilterChain filterChain = new ProxyFilterChain(this.dispatcher); - filterChain.doFilter(request, response); - - AsyncContext asyncContext = request.getAsyncContext(); - if (asyncContext != null) { - filterChain = new ProxyFilterChain(this.dispatcher); - if (asyncContext instanceof ProxyAsyncContext proxyAsyncContext) { - proxyAsyncContext.addDispatchHandler(() -> { - try { - new ProxyFilterChain(this.dispatcher).doFilter(request, response); - asyncContext.complete(); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - }); - } - } - - if (latch != null) { - latch.countDown(); - } - } - - private static class ProxyFilterChain implements FilterChain { - - @Nullable - private ServletRequest request; - - @Nullable - private ServletResponse response; - - private final List filters; - - @Nullable - private Iterator iterator; - - - /** - * Create a {@code FilterChain} with Filter's and a Servlet. - * - * @param servlet the {@link Servlet} to invoke in this {@link FilterChain} - * @param filters the {@link Filter}'s to invoke in this {@link FilterChain} - * @since 4.0.x - */ - ProxyFilterChain(DispatcherServlet servlet) { - List filters = new ArrayList<>(); - servlet.getServletContext().getFilterRegistrations().values().forEach(fr -> filters.add(((ProxyFilterRegistration) fr).getFilter())); - Assert.notNull(filters, "filters cannot be null"); - Assert.noNullElements(filters, "filters cannot contain null values"); - this.filters = initFilterList(servlet, filters.toArray(new Filter[] {})); - } - - private static List initFilterList(Servlet servlet, Filter... filters) { - Filter[] allFilters = ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)); - return Arrays.asList(allFilters); - } - - /** - * Return the request that {@link #doFilter} has been called with. - */ - @Nullable - public ServletRequest getRequest() { - return this.request; - } - - /** - * Return the response that {@link #doFilter} has been called with. - */ - @Nullable - public ServletResponse getResponse() { - return this.response; - } - - /** - * Invoke registered {@link Filter Filters} and/or {@link Servlet} also saving - * the request and response. - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { - Assert.notNull(request, "Request must not be null"); - Assert.notNull(response, "Response must not be null"); - Assert.state(this.request == null, "This FilterChain has already been called!"); - - if (this.iterator == null) { - this.iterator = this.filters.iterator(); - } - - if (this.iterator.hasNext()) { - Filter nextFilter = this.iterator.next(); - nextFilter.doFilter(request, response, this); - } - - this.request = request; - this.response = response; - } - - /** - * A filter that simply delegates to a Servlet. - */ - private static final class ServletFilterProxy implements Filter { - - private final Servlet delegateServlet; - - private ServletFilterProxy(Servlet servlet) { - Assert.notNull(servlet, "servlet cannot be null"); - this.delegateServlet = servlet; - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - - try { - if (((HttpServletResponse) response).getStatus() != HttpStatus.OK.value() && request instanceof ProxyHttpServletRequest) { - ((HttpServletRequest) request).setAttribute(RequestDispatcher.ERROR_STATUS_CODE, ((HttpServletResponse) response).getStatus()); - this.setErrorMessageAttribute((ProxyHttpServletRequest) request, (ProxyHttpServletResponse) response, null); - ((HttpServletRequest) request).setAttribute(RequestDispatcher.ERROR_REQUEST_URI, ((HttpServletRequest) request).getRequestURI()); - - ((ProxyHttpServletRequest) request).setRequestURI("/error"); - this.delegateServlet.service(request, response); - } - else { - this.delegateServlet.service(request, response); - } - } - catch (Exception e) { - if (request instanceof ProxyHttpServletRequest) { - ((HttpServletRequest) request).setAttribute(RequestDispatcher.ERROR_STATUS_CODE, HttpStatus.INTERNAL_SERVER_ERROR.value()); - this.setErrorMessageAttribute((HttpServletRequest) request, (HttpServletResponse) response, e); - ((HttpServletRequest) request).setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, e); - ((HttpServletRequest) request).setAttribute(RequestDispatcher.ERROR_REQUEST_URI, ((HttpServletRequest) request).getRequestURI()); - ((ProxyHttpServletRequest) request).setRequestURI("/error"); - } - - LOG.error("Failed processing the request to: " + ((HttpServletRequest) request).getRequestURI(), e); - - this.delegateServlet.service(request, response); - } - } - - private void setErrorMessageAttribute(HttpServletRequest request, HttpServletResponse response, Exception exception) { - if (exception != null && StringUtils.hasText(exception.getMessage())) { - request.setAttribute(RequestDispatcher.ERROR_MESSAGE, exception.getMessage()); - } - else if (response instanceof ProxyHttpServletResponse proxyResponse && StringUtils.hasText(proxyResponse.getErrorMessage())) { - request.setAttribute(RequestDispatcher.ERROR_MESSAGE, proxyResponse.getErrorMessage()); - } - else { - request.setAttribute(RequestDispatcher.ERROR_MESSAGE, HttpStatus.valueOf(response.getStatus()).getReasonPhrase()); - - } - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void destroy() { - } - - @Override - public String toString() { - return this.delegateServlet.toString(); - } - } - } - - private static class ProxyServletConfig implements ServletConfig { - - private final ServletContext servletContext; - - ProxyServletConfig(ServletContext servletContext) { - this.servletContext = servletContext; - } - - @Override - public String getServletName() { - return DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME; - } - - @Override - public ServletContext getServletContext() { - return this.servletContext; - } - - @Override - public Enumeration getInitParameterNames() { - return Collections.enumeration(new ArrayList()); - } - - @Override - public String getInitParameter(String name) { - return null; - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletContext.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletContext.java deleted file mode 100644 index 40fdbb1ca..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletContext.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterRegistration; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.ServletRegistration.Dynamic; -import jakarta.servlet.SessionCookieConfig; -import jakarta.servlet.SessionTrackingMode; -import jakarta.servlet.descriptor.JspConfigDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.util.ClassUtils; - -/** - * Empty no-op representation of {@link ServletContext} to satisfy required dependencies to - * successfully proxy incoming web requests to target web application. - * Most methods are not implemented. - * - * @author Oleg Zhurakousky - * - */ -public class ProxyServletContext implements ServletContext { - - private Log logger = LogFactory.getLog(ProxyServletContext.class); - - private static Enumeration EMPTY_ENUM = Collections.enumeration(new ArrayList()); - - @Override - public Enumeration getInitParameterNames() { - return EMPTY_ENUM; - } - - @Override - public Enumeration getAttributeNames() { - return EMPTY_ENUM; - } - - @Override - public String getContextPath() { - return ""; - } - - @Override - public ServletContext getContext(String uripath) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public int getMajorVersion() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public int getMinorVersion() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public int getEffectiveMajorVersion() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public int getEffectiveMinorVersion() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getMimeType(String file) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Set getResourcePaths(String path) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public URL getResource(String path) throws MalformedURLException { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public InputStream getResourceAsStream(String path) { - return null; - } - - @Override - public RequestDispatcher getRequestDispatcher(String path) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public RequestDispatcher getNamedDispatcher(String name) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void log(String msg) { - this.logger.info(msg); - } - - @Override - public void log(String message, Throwable throwable) { - this.logger.error(message, throwable); - } - - @Override - public String getRealPath(String path) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getServerInfo() { - return ClassUtils.isPresent("com.amazonaws.serverless.proxy.spring.SpringLambdaContainerHandler", ClassUtils.getDefaultClassLoader()) - ? "aws-serverless-java-container/6.0" - : "serverless-web-proxy"; - } - - @Override - public String getInitParameter(String name) { - return null; - - } - - @Override - public boolean setInitParameter(String name, String value) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Object getAttribute(String name) { - return null; - } - - @Override - public void setAttribute(String name, Object object) { - } - - @Override - public void removeAttribute(String name) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getServletContextName() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Dynamic addServlet(String servletName, String className) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - Map registrations = new HashMap<>(); - - @Override - public Dynamic addServlet(String servletName, Servlet servlet) { - - ProxyServletRegistration registration = new ProxyServletRegistration(servletName, servlet, this); - this.registrations.put(servletName, registration); - return registration; - } - - @Override - public Dynamic addServlet(String servletName, Class servletClass) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Dynamic addJspFile(String jspName, String jspFile) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public T createServlet(Class c) throws ServletException { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public ServletRegistration getServletRegistration(String servletName) { - return this.registrations.get(servletName); - } - - @Override - public Map getServletRegistrations() { - return this.registrations; - } - - @Override - public FilterRegistration.Dynamic addFilter(String filterName, String className) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) { - ProxyFilterRegistration registration = new ProxyFilterRegistration(filterName, filter); - filterRegistrations.put(filterName, registration); - return registration; - } - - Map filterRegistrations = new HashMap<>(); - - @Override - public FilterRegistration.Dynamic addFilter(String filterName, Class filterClass) { - try { - Filter filter = filterClass.getDeclaredConstructor().newInstance(); - ProxyFilterRegistration registration = new ProxyFilterRegistration(filterName, filter); - filterRegistrations.put(filterName, registration); - return registration; - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - - @Override - public T createFilter(Class c) throws ServletException { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public FilterRegistration getFilterRegistration(String filterName) { - return this.filterRegistrations.get(filterName); - } - - @Override - public Map getFilterRegistrations() { - return this.filterRegistrations; - } - - @Override - public SessionCookieConfig getSessionCookieConfig() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void setSessionTrackingModes(Set sessionTrackingModes) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Set getDefaultSessionTrackingModes() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public Set getEffectiveSessionTrackingModes() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void addListener(String className) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void addListener(T t) { - // TODO Auto-generated method stub - - } - - @Override - public void addListener(Class listenerClass) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public T createListener(Class c) throws ServletException { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public JspConfigDescriptor getJspConfigDescriptor() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public ClassLoader getClassLoader() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void declareRoles(String... roleNames) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getVirtualServerName() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public int getSessionTimeout() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void setSessionTimeout(int sessionTimeout) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getRequestCharacterEncoding() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void setRequestCharacterEncoding(String encoding) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public String getResponseCharacterEncoding() { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } - - @Override - public void setResponseCharacterEncoding(String encoding) { - throw new UnsupportedOperationException("This ServletContext does not represent a running web container"); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletRegistration.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletRegistration.java deleted file mode 100644 index 07474338e..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ProxyServletRegistration.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import jakarta.servlet.MultipartConfigElement; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.ServletSecurityElement; - -/** - * - * @author Oleg Zhurakousky - * @since 4.x - * - */ -public class ProxyServletRegistration implements ServletRegistration, ServletRegistration.Dynamic, Comparable { - - private final String servletName; - - private final Servlet servlet; - - private final ServletContext servletContext; - - private int loadOnStartup; - - public ProxyServletRegistration(String servletName, Servlet servlet, ServletContext servletContext) { - this.servlet = servlet; - this.servletName = servletName; - this.servletContext = servletContext; - } - - @Override - public String getName() { - return this.servletName; - } - - @Override - public String getClassName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean setInitParameter(String name, String value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String getInitParameter(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Set setInitParameters(Map initParameters) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getInitParameters() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setAsyncSupported(boolean isAsyncSupported) { - // TODO Auto-generated method stub - - } - - @Override - public void setLoadOnStartup(int loadOnStartup) { - this.loadOnStartup = loadOnStartup; - } - - public int getLoadOnStartup() { - return this.loadOnStartup; - } - - @Override - public Set setServletSecurity(ServletSecurityElement constraint) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setMultipartConfig(MultipartConfigElement multipartConfig) { - // TODO Auto-generated method stub - - } - - @Override - public void setRunAsRole(String roleName) { - // TODO Auto-generated method stub - - } - - @Override - public Set addMapping(String... urlPatterns) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getMappings() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getRunAsRole() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int compareTo(ProxyServletRegistration o) { - return Integer.compare(this.loadOnStartup, o.getLoadOnStartup()); - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ServerlessWebApplication.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ServerlessWebApplication.java deleted file mode 100644 index 1c4bcd3ed..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/main/java/org/springframework/cloud/function/serverless/web/ServerlessWebApplication.java +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.aot.AotDetector; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationContextFactory; -import org.springframework.boot.Banner; -import org.springframework.boot.BootstrapRegistryInitializer; -import org.springframework.boot.ConfigurableBootstrapContext; -import org.springframework.boot.DefaultApplicationArguments; -import org.springframework.boot.DefaultBootstrapContext; -import org.springframework.boot.DefaultPropertiesPropertySource; -import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor; -import org.springframework.boot.ResourceBanner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringApplicationRunListener; -import org.springframework.boot.SpringBootVersion; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.ansi.AnsiColor; -import org.springframework.boot.ansi.AnsiOutput; -import org.springframework.boot.ansi.AnsiStyle; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.aot.AotApplicationContextInitializer; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.support.SpringFactoriesLoader; -import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; -import org.springframework.core.metrics.ApplicationStartup; -import org.springframework.core.metrics.StartupStep; -import org.springframework.util.Assert; -import org.springframework.web.context.ConfigurableWebApplicationContext; - -/** - * - * @author Oleg Zhurakousky - * - */ -class ServerlessWebApplication extends SpringApplication { - - private static final Log logger = LogFactory.getLog(ServerlessWebApplication.class); - - private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT; - - private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT; - - private boolean allowCircularReferences; - - private boolean allowBeanDefinitionOverriding; - - private boolean logStartupInfo = true; - - private boolean lazyInitialization = false; - - private WebApplicationType webApplicationType; - - private List> initializers; - - public static ConfigurableWebApplicationContext run(Class[] primarySources, String[] args) { - return new ServerlessWebApplication(primarySources).run(args); - } - - ServerlessWebApplication(Class... classes) { - super(classes); - } - - @Override - public ConfigurableWebApplicationContext run(String... args) { - this.webApplicationType = WebApplicationType.SERVLET; - DefaultBootstrapContext bootstrapContext = createBootstrapContext(); - ConfigurableWebApplicationContext context = null; - SpringApplicationRunListeners listeners = getRunListeners(args); - listeners.starting(bootstrapContext, this.getMainApplicationClass()); - try { - ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); - ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); - Banner printedBanner = printBanner(environment); - context = (ConfigurableWebApplicationContext) createApplicationContext(); - context.setApplicationStartup(this.applicationStartup); - prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); - } - catch (Throwable ex) { - throw new IllegalStateException(ex); - } - - return context; - } - - - private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, - DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { - // Create and configure the environment - ConfigurableEnvironment environment = getOrCreateEnvironment(); - configureEnvironment(environment, applicationArguments.getSourceArgs()); - ConfigurationPropertySources.attach(environment); - listeners.environmentPrepared(bootstrapContext, environment); - DefaultPropertiesPropertySource.moveToEnd(environment); - Assert.state(!environment.containsProperty("spring.main.environment-prefix"), - "Environment prefix cannot be set via properties."); - bindToSpringApplication(environment); - ConfigurationPropertySources.attach(environment); - return environment; - } - - private ConfigurableEnvironment getOrCreateEnvironment() { - ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType); - if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) { - environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType); - } - return environment; - } - - private SpringApplicationRunListeners getRunListeners(String[] args) { - ArgumentResolver argumentResolver = ArgumentResolver.of(SpringApplication.class, this); - argumentResolver = argumentResolver.and(String[].class, args); - List listeners = getSpringFactoriesInstances(SpringApplicationRunListener.class, argumentResolver); - return new SpringApplicationRunListeners(logger, listeners, this.applicationStartup); - } - - private Banner printBanner(ConfigurableEnvironment environment) { - ResourceLoader resourceLoader = (this.getResourceLoader() != null) ? this.getResourceLoader() - : new DefaultResourceLoader(null); - SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, new SpringAwsBanner()); - return bannerPrinter.print(environment, this.getMainApplicationClass(), System.out); - } - - - private DefaultBootstrapContext createBootstrapContext() { - DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); - ArrayList bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); - bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext)); - return bootstrapContext; - } - - private List getSpringFactoriesInstances(Class type) { - return getSpringFactoriesInstances(type, null); - } - - private List getSpringFactoriesInstances(Class type, ArgumentResolver argumentResolver) { - return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver); - } - - private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, - ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, - ApplicationArguments applicationArguments, Banner printedBanner) { - context.setEnvironment(environment); - postProcessApplicationContext(context); - addAotGeneratedInitializerIfNecessary(this.initializers); - applyInitializers(context); - listeners.contextPrepared(context); - bootstrapContext.close(context); - if (this.logStartupInfo) { - logStartupInfo(context.getParent() == null); - logStartupProfileInfo(context); - } - // Add boot specific singleton beans - ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); - beanFactory.registerSingleton("springApplicationArguments", applicationArguments); - if (printedBanner != null) { - beanFactory.registerSingleton("springBootBanner", printedBanner); - } - if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) { - autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences); - if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) { - listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); - } - } - if (this.lazyInitialization) { - context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); - } - context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context)); - if (!AotDetector.useGeneratedArtifacts()) { - // Load the sources - Set sources = getAllSources(); - Assert.notEmpty(sources, "Sources must not be empty"); - load(context, sources.toArray(new Object[0])); - } - listeners.contextLoaded(context); - } - - private void addAotGeneratedInitializerIfNecessary(List> initializers) { - if (AotDetector.useGeneratedArtifacts()) { - List> aotInitializers = new ArrayList<>( - initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList()); - if (aotInitializers.isEmpty()) { - String initializerClassName = this.getMainApplicationClass().getName() + "__ApplicationContextInitializer"; - aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName)); - } - initializers.removeAll(aotInitializers); - initializers.addAll(0, aotInitializers); - } - } - - private static class PropertySourceOrderingBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered { - - private final ConfigurableApplicationContext context; - - PropertySourceOrderingBeanFactoryPostProcessor(ConfigurableApplicationContext context) { - this.context = context; - } - - @Override - public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE; - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - DefaultPropertiesPropertySource.moveToEnd(this.context.getEnvironment()); - } - - } - - private static class SpringApplicationBannerPrinter { - - static final String BANNER_LOCATION_PROPERTY = "spring.banner.location"; - - static final String DEFAULT_BANNER_LOCATION = "banner.txt"; - - private static final Banner DEFAULT_BANNER = new SpringAwsBanner(); - - private final ResourceLoader resourceLoader; - - private final Banner fallbackBanner; - - SpringApplicationBannerPrinter(ResourceLoader resourceLoader, Banner fallbackBanner) { - this.resourceLoader = resourceLoader; - this.fallbackBanner = fallbackBanner; - } - - Banner print(Environment environment, Class sourceClass, PrintStream out) { - Banner banner = getBanner(environment); - banner.printBanner(environment, sourceClass, out); - return new PrintedBanner(banner, sourceClass); - } - - private Banner getBanner(Environment environment) { - Banner textBanner = getTextBanner(environment); - if (textBanner != null) { - return textBanner; - } - if (this.fallbackBanner != null) { - return this.fallbackBanner; - } - return DEFAULT_BANNER; - } - - private Banner getTextBanner(Environment environment) { - String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION); - Resource resource = this.resourceLoader.getResource(location); - try { - if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) { - return new ResourceBanner(resource); - } - } - catch (IOException ex) { - // Ignore - } - return null; - } - - /** - * Decorator that allows a {@link Banner} to be printed again without needing to - * specify the source class. - */ - private static class PrintedBanner implements Banner { - - private final Banner banner; - - private final Class sourceClass; - - PrintedBanner(Banner banner, Class sourceClass) { - this.banner = banner; - this.sourceClass = sourceClass; - } - - @Override - public void printBanner(Environment environment, Class sourceClass, PrintStream out) { - sourceClass = (sourceClass != null) ? sourceClass : this.sourceClass; - this.banner.printBanner(environment, sourceClass, out); - } - - } - } - - private static class SpringAwsBanner implements Banner { - - private static final String[] BANNER = { "", "\n" - + " ____ _ _____ ______ _ _ _ \n" - + " / ___| _ __ _ __(_)_ __ __ _ / / \\ \\ / / ___| | | __ _ _ __ ___ | |__ __| | __ _ \n" - + " \\___ \\| '_ \\| '__| | '_ \\ / _` | / / _ \\ \\ /\\ / /\\___ \\ | | / _` | '_ ` _ \\| '_ \\ / _` |/ _` |\n" - + " ___) | |_) | | | | | | | (_| |/ / ___ \\ V V / ___) | | |__| (_| | | | | | | |_) | (_| | (_| |\n" - + " |____/| .__/|_| |_|_| |_|\\__, /_/_/ \\_\\_/\\_/ |____/ |_____\\__,_|_| |_| |_|_.__/ \\__,_|\\__,_|\n" - + " |_| |___/ \n" - + "" }; - - private static final String SPRING_BOOT = " :: Spring Boot :: "; - - private static final int STRAP_LINE_SIZE = 42; - - @Override - public void printBanner(Environment environment, Class sourceClass, PrintStream printStream) { - for (String line : BANNER) { - printStream.println(line); - } - String version = SpringBootVersion.getVersion(); - version = (version != null) ? " (v" + version + ")" : ""; - StringBuilder padding = new StringBuilder(); - while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) { - padding.append(" "); - } - - printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(), - AnsiStyle.FAINT, version)); - printStream.println(); - } - - } - - private static class SpringApplicationRunListeners { - - private final List listeners; - - private final ApplicationStartup applicationStartup; - - SpringApplicationRunListeners(Log log, List listeners, - ApplicationStartup applicationStartup) { - this.listeners = List.copyOf(listeners); - this.applicationStartup = applicationStartup; - } - - void starting(ConfigurableBootstrapContext bootstrapContext, Class mainApplicationClass) { - doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext), - (step) -> { - if (mainApplicationClass != null) { - step.tag("mainApplicationClass", mainApplicationClass.getName()); - } - }); - } - - void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) { - doWithListeners("spring.boot.application.environment-prepared", - (listener) -> listener.environmentPrepared(bootstrapContext, environment)); - } - - void contextPrepared(ConfigurableApplicationContext context) { - doWithListeners("spring.boot.application.context-prepared", (listener) -> listener.contextPrepared(context)); - } - - void contextLoaded(ConfigurableApplicationContext context) { - doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context)); - } - private void doWithListeners(String stepName, Consumer listenerAction) { - doWithListeners(stepName, listenerAction, null); - } - - private void doWithListeners(String stepName, Consumer listenerAction, - Consumer stepAction) { - StartupStep step = this.applicationStartup.start(stepName); - this.listeners.forEach(listenerAction); - if (stepAction != null) { - stepAction.accept(step); - } - step.end(); - } - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java deleted file mode 100644 index 9e0411eb1..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2023-2023 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.serverless.web; - -import java.util.List; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.http.HttpServletRequest; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - - -import org.springframework.cloud.function.test.app.Pet; -import org.springframework.cloud.function.test.app.PetStoreSpringAppConfig; -import org.springframework.http.HttpStatus; -import org.springframework.security.test.context.support.WithMockUser; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class RequestResponseTests { - - private ObjectMapper mapper = new ObjectMapper(); - - private ProxyMvc mvc; - - @BeforeEach - public void before() { - this.mvc = ProxyMvc.INSTANCE(ProxyErrorController.class, PetStoreSpringAppConfig.class); - } - - @AfterEach - public void after() { - this.mvc.stop(); - } - - @Test - public void validateAccessDeniedWithCustomHandler() throws Exception { - HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/foo"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - assertThat(response.getErrorMessage()).isEqualTo("Can't touch this"); - assertThat(response.getStatus()).isEqualTo(403); - } - - @Test - public void validateGetListOfPojos() throws Exception { - HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - TypeReference> tr = new TypeReference>() { - }; - List pets = mapper.readValue(response.getContentAsByteArray(), tr); - assertThat(pets.size()).isEqualTo(10); - assertThat(pets.get(0)).isInstanceOf(Pet.class); - } - - @Test - public void validateGetListOfPojosWithParam() throws Exception { - ProxyHttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets"); - request.setParameter("limit", "5"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - TypeReference> tr = new TypeReference>() { - }; - List pets = mapper.readValue(response.getContentAsByteArray(), tr); - assertThat(pets.size()).isEqualTo(5); - assertThat(pets.get(0)).isInstanceOf(Pet.class); - } - - @WithMockUser("spring") - @Test - public void validateGetPojo() throws Exception { - HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets/6e3cc370-892f-4efe-a9eb-82926ff8cc5b"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - Pet pet = mapper.readValue(response.getContentAsByteArray(), Pet.class); - assertThat(pet).isNotNull(); - assertThat(pet.getName()).isNotEmpty(); - } - - @Test - public void errorThrownFromMethod() throws Exception { - HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets/2"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value()); - assertThat(response.getErrorMessage()).isEqualTo("No such Dog"); - } - - @Test - public void errorUnexpectedWhitelabel() throws Exception { - HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets/2/3/4"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value()); - } - - @Test - public void validatePostWithBody() throws Exception { - ProxyHttpServletRequest request = new ProxyHttpServletRequest(null, "POST", "/pets/"); - String jsonPet = "{\n" - + " \"id\":\"1234\",\n" - + " \"breed\":\"Canish\",\n" - + " \"name\":\"Foo\",\n" - + " \"date\":\"2012-04-23T18:25:43.511Z\"\n" - + "}"; - request.setContent(jsonPet.getBytes()); - request.setContentType("application/json"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - Pet pet = mapper.readValue(response.getContentAsByteArray(), Pet.class); - assertThat(pet).isNotNull(); - assertThat(pet.getName()).isNotEmpty(); - } - - @Test - public void validatePostAsyncWithBody() throws Exception { - ProxyHttpServletRequest request = new ProxyHttpServletRequest(null, "POST", "/petsAsync/"); - String jsonPet = "{\n" - + " \"id\":\"1234\",\n" - + " \"breed\":\"Canish\",\n" - + " \"name\":\"Foo\",\n" - + " \"date\":\"2012-04-23T18:25:43.511Z\"\n" - + "}"; - request.setContent(jsonPet.getBytes()); - request.setContentType("application/json"); - ProxyHttpServletResponse response = new ProxyHttpServletResponse(); - mvc.service(request, response); - Pet pet = mapper.readValue(response.getContentAsByteArray(), Pet.class); - assertThat(pet).isNotNull(); - assertThat(pet.getName()).isNotEmpty(); - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/Pet.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/Pet.java deleted file mode 100644 index c0b8f0689..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/Pet.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2023-2023 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.test.app; - -import java.util.Date; - -public class Pet { - private String id; - private String breed; - private String name; - private Date dateOfBirth; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getBreed() { - return breed; - } - - public void setBreed(String breed) { - this.breed = breed; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetData.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetData.java deleted file mode 100644 index 90b2a736f..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetData.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2023-2023 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.test.app; - - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -public class PetData { - private static List breeds = new ArrayList<>(); - static { - breeds.add("Afghan Hound"); - breeds.add("Beagle"); - breeds.add("Bernese Mountain Dog"); - breeds.add("Bloodhound"); - breeds.add("Dalmatian"); - breeds.add("Jack Russell Terrier"); - breeds.add("Norwegian Elkhound"); - } - - private static List names = new ArrayList<>(); - static { - names.add("Bailey"); - names.add("Bella"); - names.add("Max"); - names.add("Lucy"); - names.add("Charlie"); - names.add("Molly"); - names.add("Buddy"); - names.add("Daisy"); - names.add("Rocky"); - names.add("Maggie"); - names.add("Jake"); - names.add("Sophie"); - names.add("Jack"); - names.add("Sadie"); - names.add("Toby"); - names.add("Chloe"); - names.add("Cody"); - names.add("Bailey"); - names.add("Buster"); - names.add("Lola"); - names.add("Duke"); - names.add("Zoe"); - names.add("Cooper"); - names.add("Abby"); - names.add("Riley"); - names.add("Ginger"); - names.add("Harley"); - names.add("Roxy"); - names.add("Bear"); - names.add("Gracie"); - names.add("Tucker"); - names.add("Coco"); - names.add("Murphy"); - names.add("Sasha"); - names.add("Lucky"); - names.add("Lily"); - names.add("Oliver"); - names.add("Angel"); - names.add("Sam"); - names.add("Princess"); - names.add("Oscar"); - names.add("Emma"); - names.add("Teddy"); - names.add("Annie"); - names.add("Winston"); - names.add("Rosie"); - } - - public static List getBreeds() { - return breeds; - } - - public static List getNames() { - return names; - } - - public static String getRandomBreed() { - return breeds.get(ThreadLocalRandom.current().nextInt(0, breeds.size() - 1)); - } - - public static String getRandomName() { - return names.get(ThreadLocalRandom.current().nextInt(0, names.size() - 1)); - } - - public static Date getRandomDoB() { - GregorianCalendar gc = new GregorianCalendar(); - - int year = ThreadLocalRandom.current().nextInt(Calendar.getInstance().get(Calendar.YEAR) - 15, - Calendar.getInstance().get(Calendar.YEAR)); - - gc.set(Calendar.YEAR, year); - - int dayOfYear = ThreadLocalRandom.current().nextInt(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR)); - - gc.set(Calendar.DAY_OF_YEAR, dayOfYear); - return gc.getTime(); - } -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java deleted file mode 100644 index 2c61478af..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2023-2023 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.test.app; - -import java.io.IOException; -import java.util.Collections; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.context.SecurityContextHolderFilter; -import org.springframework.web.filter.GenericFilterBean; -import org.springframework.web.servlet.HandlerAdapter; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - - -@Configuration -@Import({ PetsController.class }) -@EnableWebSecurity -public class PetStoreSpringAppConfig { - - /* - * Create required HandlerMapping, to avoid several default HandlerMapping - * instances being created - */ - @Bean - public HandlerMapping handlerMapping() { - return new RequestMappingHandlerMapping(); - } - - /* - * Create required HandlerAdapter, to avoid several default HandlerAdapter - * instances being created - */ - @Bean - public HandlerAdapter handlerAdapter() { - return new RequestMappingHandlerAdapter(); - } - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - .addFilterBefore(new GenericFilterBean() { - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - SecurityContext securityContext = SecurityContextHolder.getContext(); - securityContext.setAuthentication(UsernamePasswordAuthenticationToken.authenticated("user", "password", - Collections.singleton(new SimpleGrantedAuthority("USER")))); - HttpSession session = ((HttpServletRequest) request).getSession(); - session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext); - chain.doFilter(request, response); - } - }, SecurityContextHolderFilter.class) - .securityMatcher("/foo") - .authorizeHttpRequests(authorize -> authorize - .anyRequest().hasRole("FOO") - ) - .exceptionHandling(f -> f.accessDeniedHandler(accessDeniedHandler())); - return http.build(); - } - - @Bean - public AccessDeniedHandler accessDeniedHandler() { - - return new AccessDeniedHandler() { - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, - AccessDeniedException accessDeniedException) throws IOException, ServletException { - response.sendError(403, "Can't touch this"); - } - }; - } - -} diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java deleted file mode 100644 index 89a09ba14..000000000 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2023-2023 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.test.app; - -import java.security.Principal; -import java.util.Optional; -import java.util.UUID; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.async.DeferredResult; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - - -@RestController -@EnableWebMvc -public class PetsController { - - @RequestMapping(path = "/petsAsync/", method = RequestMethod.POST) - public DeferredResult createPetAsync(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - DeferredResult result = new DeferredResult(); - result.setResult(dbPet); - return result; - } - - @RequestMapping(path = "/pets/", method = RequestMethod.POST) - public Pet createPet(@RequestBody Pet newPet) { - if (newPet.getName() == null || newPet.getBreed() == null) { - return null; - } - - Pet dbPet = newPet; - dbPet.setId(UUID.randomUUID().toString()); - return dbPet; - } - - @RequestMapping(path = "/pets", method = RequestMethod.GET) - public Pet[] listPets(@RequestParam("limit") Optional limit, Principal principal) { - int queryLimit = 10; - if (limit.isPresent()) { - queryLimit = limit.get(); - } - - Pet[] outputPets = new Pet[queryLimit]; - - for (int i = 0; i < queryLimit; i++) { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setName(PetData.getRandomName()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - outputPets[i] = newPet; - } - - return outputPets; - } - - @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET) - public Pet listPets(@PathVariable String petId) { - if (petId.equals("2")) { - throw new DogNotFoundException(); - } - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - - @RequestMapping(path = "/foo", method = RequestMethod.GET) - public Pet foo() { - Pet newPet = new Pet(); - newPet.setId(UUID.randomUUID().toString()); - newPet.setBreed(PetData.getRandomBreed()); - newPet.setDateOfBirth(PetData.getRandomDoB()); - newPet.setName(PetData.getRandomName()); - return newPet; - } - - @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such Dog") // 404 - public class DogNotFoundException extends RuntimeException { - // ... - } -} diff --git a/spring-cloud-function-context/pom.xml b/spring-cloud-function-context/pom.xml deleted file mode 100644 index 12e023305..000000000 --- a/spring-cloud-function-context/pom.xml +++ /dev/null @@ -1,199 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-context - jar - spring-cloud-function-context - Implementation of core API for Spring Cloud Function - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - 1.10.2 - - - - - net.jodah - typetools - 0.6.2 - - - org.springframework.boot - spring-boot-autoconfigure - - - org.springframework.cloud - spring-cloud-function-core - - - org.springframework - spring-messaging - - - org.springframework - spring-web - true - - - com.fasterxml.jackson.module - jackson-module-kotlin - true - - - org.springframework.boot - spring-boot-configuration-processor - true - - - com.google.code.gson - gson - true - - - com.fasterxml.jackson.core - jackson-databind - true - - - org.springframework.boot - spring-boot-starter-test - true - - - com.vaadin.external.google - android-json - - - - - io.projectreactor - reactor-test - test - - - - com.fasterxml.jackson.core - jackson-databind - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - true - - - org.jetbrains.kotlin - kotlin-reflect - true - - - org.jetbrains.kotlinx - kotlinx-coroutines-reactor - true - - - - - io.cloudevents - cloudevents-spring - 2.2.0 - true - - - - - org.springframework.boot - spring-boot-starter-actuator - true - - - - - io.micrometer - micrometer-observation - true - - - io.micrometer - micrometer-core - true - - - io.micrometer - micrometer-tracing - true - - - io.micrometer - micrometer-observation-test - test - - - io.micrometer - micrometer-tracing-bridge-otel - test - - - - - - - kotlin-maven-plugin - org.jetbrains.kotlin - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/main/java - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - - diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/actuator/FunctionsEndpoint.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/actuator/FunctionsEndpoint.java deleted file mode 100644 index 008a969db..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/actuator/FunctionsEndpoint.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2021-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.actuator; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; - -/** - * - * Actuator endpoint to access {@link FunctionCatalog}. - * - * @author Oleg Zhurakousky - * @since 3.2 - */ -@Endpoint(id = "functions") -public class FunctionsEndpoint { - - private final FunctionCatalog functionCatalog; - - public FunctionsEndpoint(FunctionCatalog functionCatalog) { - this.functionCatalog = functionCatalog; - } - - @ReadOperation - public Map> listAll() { - Map> allFunctions = new TreeMap<>(); - Set names = functionCatalog.getNames(null); - for (String name : names) { - FunctionInvocationWrapper function = functionCatalog.lookup(name); - Map functionMap = new LinkedHashMap<>(); - if (function.isFunction()) { - functionMap.put("type", "FUNCTION"); - functionMap.put("input-type", this.toSimplePolyIn(function)); - functionMap.put("output-type", this.toSimplePolyOut(function)); - } - else if (function.isConsumer()) { - functionMap.put("type", "CONSUMER"); - functionMap.put("input-type", this.toSimplePolyIn(function)); - } - else { - functionMap.put("type", "SUPPLIER"); - functionMap.put("output-type", this.toSimplePolyOut(function)); - } - allFunctions.put(name, functionMap); - } - - - return allFunctions; - } - - - private String toSimplePolyOut(FunctionInvocationWrapper function) { - return FunctionTypeUtils.getRawType(function.getItemType(function.getOutputType())).getSimpleName().toLowerCase(); - } - - private String toSimplePolyIn(FunctionInvocationWrapper function) { - return FunctionTypeUtils.getRawType(function.getItemType(function.getInputType())).getSimpleName().toLowerCase(); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventHeaderEnricher.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventHeaderEnricher.java deleted file mode 100644 index 3e5b3fa8f..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventHeaderEnricher.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -/** - * Strategy that should be implemented by the user to help with outgoing Cloud Event - * headers.
- *
- * NOTE: The provided instance of {@link CloudEventMessageBuilder} may or may not be initialized - * with default values, so it is the responsibility of the user to ensure that all required Cloud Events - * attributes are set. That said, Spring frameworks which utilize this interface - * will ensure that the provided {@link CloudEventMessageBuilder} is initialized with default values, leaving - * you responsible to only set the attributes you need.
- * Once implemented, simply configure it as a bean and the framework will invoke it before - * the outbound Cloud Event Message is finalized. - * - *
- * @Bean
- * public CloudEventHeaderEnricher cloudEventHeaderEnricher() {
- *  return headers -> {
- *   return headers.setSource("https://interface21.com/").setType("com.interface21");
- *  };
- * }
- * 
- * - * @author Oleg Zhurakousky - * @author Dave Syer - * @since 3.1 - */ -@FunctionalInterface -public interface CloudEventHeaderEnricher { - - /** - * @param attributes instance of {@link CloudEventContext} - * @return modified {@link CloudEventContext} - */ - /** - * Will provide access to an open instance of {@link CloudEventMessageBuilder} so you - * can add additional attributes and headers. - * @param messageBuilder open instance of {@link CloudEventMessageBuilder} - * @return instance of {@link CloudEventMessageBuilder} - */ - CloudEventMessageBuilder enrich(CloudEventMessageBuilder messageBuilder); - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageBuilder.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageBuilder.java deleted file mode 100644 index f7f55ec45..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageBuilder.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.net.URI; -import java.time.OffsetDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Message builder which is aware of Cloud Event semantics. - * It provides type-safe setters for v1.0 Cloud Event attributes while - * supporting all other versions via convenient - * {@link #setHeader(String, Object)} method. - * - * @author Oleg Zhurakousky - * @since 3.1 - */ -public final class CloudEventMessageBuilder { - - protected Log logger = LogFactory.getLog(this.getClass()); - - private final Map headers; - - private T data; - - private CloudEventMessageBuilder(Map headers) { - this.headers = headers == null ? new HashMap<>() : headers; - } - - public static CloudEventMessageBuilder withData(T data) { - CloudEventMessageBuilder builder = new CloudEventMessageBuilder(null); - builder.data = data; - return builder; - } - - public static CloudEventMessageBuilder fromMessage(Message message) { - CloudEventMessageBuilder builder = new CloudEventMessageBuilder(new HashMap<>(message.getHeaders())); - builder.data = message.getPayload(); - return builder; - } - - public CloudEventMessageBuilder setId(String id) { - this.headers.put(CloudEventMessageUtils.ID, id); - return this; - } - - public CloudEventMessageBuilder setSource(URI uri) { - this.headers.put(CloudEventMessageUtils.SOURCE, uri); - return this; - } - - public CloudEventMessageBuilder setSource(String uri) { - this.headers.put(CloudEventMessageUtils.SOURCE, URI.create(uri)); - return this; - } - - public CloudEventMessageBuilder setSpecVersion(String specversion) { - this.headers.put(CloudEventMessageUtils.SPECVERSION, specversion); - return this; - } - - public CloudEventMessageBuilder setType(String type) { - this.headers.put(CloudEventMessageUtils.TYPE, type); - return this; - } - - public CloudEventMessageBuilder setDataContentType(String dataContentType) { - this.headers.put(CloudEventMessageUtils.DATACONTENTTYPE, dataContentType); - return this; - } - - public CloudEventMessageBuilder setDataSchema(URI dataSchema) { - this.headers.put(CloudEventMessageUtils.DATASCHEMA, dataSchema); - return this; - } - - public CloudEventMessageBuilder setDataSchema(String dataSchema) { - this.headers.put(CloudEventMessageUtils.DATASCHEMA, URI.create(dataSchema)); - return this; - } - - public CloudEventMessageBuilder setSubject(String subject) { - this.headers.put(CloudEventMessageUtils.SUBJECT, subject); - return this; - } - - public CloudEventMessageBuilder setTime(OffsetDateTime time) { - this.headers.put(CloudEventMessageUtils.TIME, time); - return this; - } - - public CloudEventMessageBuilder setTime(String time) { - this.headers.put(CloudEventMessageUtils.TIME, OffsetDateTime.parse(time)); - return this; - } - - public CloudEventMessageBuilder setHeader(String key, Object value) { - this.headers.put(key, value); - return this; - } - - public CloudEventMessageBuilder copyHeaders(Map headers) { - this.headers.putAll(headers); - return this; - } - - /** - * Returns a snapshot of the headers {@link Map} at the time this method is called. - * The returned Map is read-only. - * - * @return map of headers - */ - public Map toHeadersMap() { - return Collections.unmodifiableMap(this.headers); - } - - /** - * Will build the message ensuring that the Cloud Event attributes are all - * prefixed with the prefix determined by the framework. If you want to - * use a specific prefix please use {@link #build(String)} method. - * @return instance of {@link Message} - */ - public Message build() { - return this.doBuild(CloudEventMessageUtils.determinePrefixToUse(this.headers)); - } - - /** - * Will build the message ensuring that the Cloud Event attributes are - * prefixed with the 'attributePrefixToUse'. - * - * @param attributePrefixToUse prefix to use for attributes - * @return instance of {@link Message} - */ - public Message build(String attributePrefixToUse) { - Assert.isTrue(attributePrefixToUse.equals(CloudEventMessageUtils.DEFAULT_ATTR_PREFIX) - || attributePrefixToUse.equals(CloudEventMessageUtils.KAFKA_ATTR_PREFIX) - || attributePrefixToUse.equals(CloudEventMessageUtils.AMQP_ATTR_PREFIX), "Supported prefixes are " - + CloudEventMessageUtils.DEFAULT_ATTR_PREFIX - + ", " + CloudEventMessageUtils.KAFKA_ATTR_PREFIX - + ", " + CloudEventMessageUtils.AMQP_ATTR_PREFIX - + ". Was " + attributePrefixToUse); - if (StringUtils.hasText(attributePrefixToUse)) { - String[] keys = this.headers.keySet().toArray(new String[] {}); - for (String key : keys) { - if (key.startsWith(CloudEventMessageUtils.DEFAULT_ATTR_PREFIX)) { - this.swapPrefix(key, CloudEventMessageUtils.DEFAULT_ATTR_PREFIX, attributePrefixToUse); - } - else if (key.startsWith(CloudEventMessageUtils.AMQP_ATTR_PREFIX)) { - this.swapPrefix(key, CloudEventMessageUtils.AMQP_ATTR_PREFIX, attributePrefixToUse); - } - else if (key.startsWith(CloudEventMessageUtils.KAFKA_ATTR_PREFIX)) { - this.swapPrefix(key, CloudEventMessageUtils.KAFKA_ATTR_PREFIX, attributePrefixToUse); - } - } - } - return doBuild(attributePrefixToUse); - } - - private void swapPrefix(String key, String currentPrefix, String newPrefix) { - Object value = headers.remove(key); - key = key.substring(currentPrefix.length()); - this.headers.put(newPrefix + key, value); - } - - private Message doBuild(String prefix) { - if (!this.headers.containsKey(prefix + CloudEventMessageUtils._SPECVERSION)) { - this.headers.put(prefix + CloudEventMessageUtils._SPECVERSION, "1.0"); - } - if (!this.headers.containsKey(prefix + CloudEventMessageUtils._ID)) { - this.headers.put(prefix + CloudEventMessageUtils._ID, UUID.randomUUID().toString()); - } - this.headers.put(MessageUtils.MESSAGE_TYPE, CloudEventMessageUtils.CLOUDEVENT_VALUE); - - if (!this.headers.containsKey(prefix + CloudEventMessageUtils._TYPE)) { - this.headers.put(prefix + CloudEventMessageUtils._TYPE, this.data.getClass().getName()); - } - if (!this.headers.containsKey(prefix + CloudEventMessageUtils._SOURCE)) { - this.headers.put(prefix + CloudEventMessageUtils._SOURCE, URI.create("https://spring.io/")); - } - MessageHeaders headers = new MessageHeaders(this.headers); - GenericMessage message = new GenericMessage(this.data, headers); - Assert.isTrue(CloudEventMessageUtils.isCloudEvent(message), "The message does not appear to be a valid Cloud Event, " - + "since one of the required attributes (id, specversion, type, source) is missing"); - return message; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtils.java deleted file mode 100644 index 47ad97e04..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtils.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.net.URI; -import java.time.OffsetDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.cloud.function.context.message.MessageUtils.MessageStructureWithCaseInsensitiveHeaderKeys; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.ContentTypeResolver; -import org.springframework.messaging.converter.DefaultContentTypeResolver; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.StringUtils; - -/** - * Miscellaneous utility methods to assist with representing Cloud Event as Spring - * {@link Message}.
- * Primarily intended for the internal use within Spring-based frameworks and - * integrations. - * - * @author Oleg Zhurakousky - * @author Dave Syer - * @author Chris Bono - * @since 3.1 - */ -public final class CloudEventMessageUtils { - - private static final ContentTypeResolver contentTypeResolver = new DefaultContentTypeResolver() { - - @Override - public MimeType resolve(@Nullable MessageHeaders headers) { - if (headers.containsKey("content-type")) { // this is temporary workaround for RSocket - return MimeType.valueOf(headers.get("content-type").toString()); - } - return super.resolve(headers); - } - - }; - - private CloudEventMessageUtils() { - } - - //=========== INTERNAL USE ONLY == - static String _DATA = "data"; - - static String _ID = "id"; - - static String _SOURCE = "source"; - - static String _SPECVERSION = "specversion"; - - static String _TYPE = "type"; - - static String _DATACONTENTTYPE = "datacontenttype"; - - static String _DATASCHEMA = "dataschema"; - - static String _SCHEMAURL = "schemaurl"; - - static String _SUBJECT = "subject"; - - static String _TIME = "time"; - // ================================ - - /** - * String value of 'cloudevent'. Typically used as {@link MessageUtils#MESSAGE_TYPE} - */ - public static String CLOUDEVENT_VALUE = "cloudevent"; - - /** - * String value of 'application/cloudevents' mime type. - */ - public static String APPLICATION_CLOUDEVENTS_VALUE = "application/cloudevents"; - - /** - * {@link MimeType} instance representing 'application/cloudevents' mime type. - */ - public static MimeType APPLICATION_CLOUDEVENTS = MimeTypeUtils.parseMimeType(APPLICATION_CLOUDEVENTS_VALUE); - - /** - * Prefix for attributes. - */ - public static String DEFAULT_ATTR_PREFIX = "ce-"; - - /** - * AMQP attributes prefix. - */ - public static String AMQP_ATTR_PREFIX = "cloudEvents:"; - - /** - * Prefix for attributes. - */ - public static String KAFKA_ATTR_PREFIX = "ce_"; - - /** - * Value for 'data' attribute. - */ - public static String DATA = DEFAULT_ATTR_PREFIX + _DATA; - - /** - * Value for 'id' attribute. - */ - public static String ID = DEFAULT_ATTR_PREFIX + _ID; - - /** - * Value for 'source' attribute. - */ - public static String SOURCE = DEFAULT_ATTR_PREFIX + _SOURCE; - - /** - * Value for 'specversion' attribute. - */ - public static String SPECVERSION = DEFAULT_ATTR_PREFIX + _SPECVERSION; - - /** - * Value for 'type' attribute. - */ - public static String TYPE = DEFAULT_ATTR_PREFIX + _TYPE; - - /** - * Value for 'datacontenttype' attribute. - */ - public static String DATACONTENTTYPE = DEFAULT_ATTR_PREFIX + _DATACONTENTTYPE; - - /** - * Value for 'dataschema' attribute. - */ - public static String DATASCHEMA = DEFAULT_ATTR_PREFIX + _DATASCHEMA; - - /** - * V03 name for 'dataschema' attribute. - */ - public static final String SCHEMAURL = DEFAULT_ATTR_PREFIX + _SCHEMAURL; - - /** - * Value for 'subject' attribute. - */ - public static String SUBJECT = DEFAULT_ATTR_PREFIX + _SUBJECT; - - /** - * Value for 'time' attribute. - */ - public static String TIME = DEFAULT_ATTR_PREFIX + _TIME; - - - public static String getId(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (String) message.getHeaders().get(prefix + MessageHeaders.ID); - } - - public static URI getSource(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return safeGetURI(message.getHeaders(), prefix + _SOURCE); - } - - public static String getSpecVersion(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (String) message.getHeaders().get(prefix + _SPECVERSION); - } - - public static String getType(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (String) message.getHeaders().get(prefix + _TYPE); - } - - public static String getDataContentType(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (String) message.getHeaders().get(prefix + _DATACONTENTTYPE); - } - - public static URI getDataSchema(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return safeGetURI(message.getHeaders(), prefix + _DATASCHEMA); - } - - public static String getSubject(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (String) message.getHeaders().get(prefix + _SUBJECT); - } - - public static OffsetDateTime getTime(Message message) { - String prefix = determinePrefixToUse(message.getHeaders()); - return (OffsetDateTime) message.getHeaders().get(prefix + _TIME); - } - - @SuppressWarnings("unchecked") - public static T getData(Message message) { - return (T) message.getPayload(); - } - - public static Map getAttributes(Message message) { - return message.getHeaders().entrySet().stream() - .filter(e -> isAttribute(e.getKey())) - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); - } - - /** - * This method does several things. - * First it canonicalizes Cloud Events attributes ensuring that they are all prefixed - * with 'ce-' prefix regardless where they came from. - * It also transforms structured-mode Cloud Event to binary-mode and then canonicalizes attributes - * as well as described in the previous sentence. - */ - @SuppressWarnings("unchecked") - static Message toCanonical(Message inputMessage, MessageConverter messageConverter) { - inputMessage = canonicalizeHeadersWithPossibleCopy(inputMessage); - Map headers = new HashMap<>(inputMessage.getHeaders()); - - boolean isCloudEvent = isCloudEvent(inputMessage); - if (isCloudEvent && headers.containsKey("content-type")) { - inputMessage = MessageBuilder.fromMessage(inputMessage).setHeader(MessageHeaders.CONTENT_TYPE, headers.get("content-type")).build(); - } - MimeType contentType = contentTypeResolver.resolve(inputMessage.getHeaders()); - String inputContentType = (String) inputMessage.getHeaders().get(DATACONTENTTYPE); - // first check the obvious and see if content-type is `cloudevents` - if (!isCloudEvent && contentType != null) { - // structured-mode - - if (contentType.getType().equals(APPLICATION_CLOUDEVENTS.getType()) && contentType - .getSubtype().startsWith(APPLICATION_CLOUDEVENTS.getSubtype())) { - - String dataContentType = StringUtils.hasText(inputContentType) ? inputContentType - : MimeTypeUtils.APPLICATION_JSON_VALUE; - - String suffix = contentType.getSubtypeSuffix() == null ? "json" : contentType.getSubtypeSuffix(); - MimeType cloudEventDeserializationContentType = MimeTypeUtils - .parseMimeType(contentType.getType() + "/" + suffix); - Message cloudEventMessage = MessageBuilder.fromMessage(inputMessage) - .setHeader(MessageHeaders.CONTENT_TYPE, cloudEventDeserializationContentType) - .setHeader(DATACONTENTTYPE, dataContentType).build(); - Map structuredCloudEvent = (Map) messageConverter - .fromMessage(cloudEventMessage, Map.class); - canonicalizeHeaders(structuredCloudEvent, true); - return buildBinaryMessageFromStructuredMap(structuredCloudEvent, - inputMessage.getHeaders()); - } - } - else if (StringUtils.hasText(inputContentType)) { - // binary-mode, but DATACONTENTTYPE was specified explicitly so we set it as CT to ensure proper message converters are used. - return MessageBuilder.fromMessage(inputMessage).setHeader(MessageHeaders.CONTENT_TYPE, inputContentType) - .build(); - } - return inputMessage; - } - - /** - * Attempts to {@link #canonicalizeHeaders canonicalize} the headers of a message. - * @param message the message - * @return a copy of the message with the canonicalized headers or the passed in unmodified message if no - * headers were canonicalized - */ - // VisibleForTesting - static Message canonicalizeHeadersWithPossibleCopy(Message message) { - Map headers = new HashMap<>(message.getHeaders()); - boolean headersModified = canonicalizeHeaders(headers, false); - if (headersModified) { - message = MessageBuilder.fromMessage(message) - .removeHeaders("*") - .copyHeaders(headers) - .build(); - } - return message; - } - - /** - * Will canonicalize Cloud Event attributes (headers) by ensuring canonical - * prefix for all attributes and extensions regardless of where they came from. - * The canonical prefix is 'ce-'. - * - * So, for example 'ce_source' will become 'ce-source'. - * @param headers message headers - * @param structured boolean signifying that headers map represents structured Cloud Event - * at which point attributes without any prefix will still be treated as - * Cloud Event attributes. - * @return whether the headers were modified during the process - */ - private static boolean canonicalizeHeaders(Map headers, boolean structured) { - boolean modified = false; - String[] keys = headers.keySet().toArray(new String[] {}); - for (String key : keys) { - if (key.startsWith(DEFAULT_ATTR_PREFIX)) { - Object value = headers.remove(key); - String newKey = DEFAULT_ATTR_PREFIX + key.substring(DEFAULT_ATTR_PREFIX.length()); - headers.put(newKey, value); - modified |= (!Objects.equals(key, newKey)); - } - else if (key.startsWith(KAFKA_ATTR_PREFIX)) { - Object value = headers.remove(key); - key = key.substring(KAFKA_ATTR_PREFIX.length()); - headers.put(DEFAULT_ATTR_PREFIX + key, value); - modified = true; - } - else if (key.startsWith(AMQP_ATTR_PREFIX)) { - Object value = headers.remove(key); - key = key.substring(AMQP_ATTR_PREFIX.length()); - headers.put(DEFAULT_ATTR_PREFIX + key, value); - modified = true; - } - else if (structured) { - Object value = headers.remove(key); - headers.put(DEFAULT_ATTR_PREFIX + key, value); - modified = true; - } - } - return modified; - } - - /** - * Determines attribute prefix based on the presence of certain well defined headers. - * @param messageHeaders map of message headers - * @return prefix (e.g., 'ce_' or 'ce-' etc.) - */ - static String determinePrefixToUse(Map messageHeaders) { - return determinePrefixToUse(messageHeaders, false); - } - - static String determinePrefixToUse(Map messageHeaders, boolean strict) { - String targetProtocol = (String) messageHeaders.get(MessageUtils.TARGET_PROTOCOL); - String prefix = determinePrefixToUse(targetProtocol); - if (StringUtils.hasText(prefix) && (strict || StringUtils.hasText((String) messageHeaders.get(prefix + _SPECVERSION)))) { - return prefix; - } - else { - for (String key : messageHeaders.keySet()) { - if (key.startsWith(DEFAULT_ATTR_PREFIX)) { - return DEFAULT_ATTR_PREFIX; - } - else if (key.startsWith(KAFKA_ATTR_PREFIX)) { - return KAFKA_ATTR_PREFIX; - } - else if (key.startsWith(AMQP_ATTR_PREFIX)) { - return AMQP_ATTR_PREFIX; - } - } - } - - return DEFAULT_ATTR_PREFIX; - } - - /** - * Determines attribute prefix based on the provided target protocol. - * @param targetProtocol target protocol (see {@link MessageUtils#TARGET_PROTOCOL} - * @return prefix (e.g., 'ce_' or 'ce-' etc.) - */ - static String determinePrefixToUse(String targetProtocol) { - if (StringUtils.hasText(targetProtocol)) { - if (Protocols.KAFKA.equals(targetProtocol)) { - return CloudEventMessageUtils.KAFKA_ATTR_PREFIX; - } - else if (Protocols.AMQP.equals(targetProtocol)) { - return CloudEventMessageUtils.AMQP_ATTR_PREFIX; - } - else if (Protocols.HTTP.equals(targetProtocol)) { - return CloudEventMessageUtils.DEFAULT_ATTR_PREFIX; - } - } - return ""; - } - - /** - * Will check for the existence of required attributes. Assumes attributes (headers) - * are in canonical form. - * @param message input {@link Message} - * @return true if this Message represents Cloud Event in binary-mode - */ - public static boolean isCloudEvent(Message message) { - MessageStructureWithCaseInsensitiveHeaderKeys _message = MessageUtils.toCaseInsensitiveHeadersStructure(message); - return (_message.getHeaders().containsKey(SPECVERSION) - && _message.getHeaders().containsKey(TYPE) - && _message.getHeaders().containsKey(SOURCE)) - || - (_message.getHeaders().containsKey(_SPECVERSION) - && _message.getHeaders().containsKey(_TYPE) - && _message.getHeaders().containsKey(_SOURCE)) - || - (_message.getHeaders().containsKey(AMQP_ATTR_PREFIX + _SPECVERSION) - && _message.getHeaders().containsKey(AMQP_ATTR_PREFIX + _TYPE) - && _message.getHeaders().containsKey(AMQP_ATTR_PREFIX + _SOURCE)) - || - (_message.getHeaders().containsKey(KAFKA_ATTR_PREFIX + _SPECVERSION) - && _message.getHeaders().containsKey(KAFKA_ATTR_PREFIX + _TYPE) - && _message.getHeaders().containsKey(KAFKA_ATTR_PREFIX + _SOURCE)); - } - - private static boolean isAttribute(String key) { - return key.startsWith(DEFAULT_ATTR_PREFIX) || key.startsWith(AMQP_ATTR_PREFIX) || key.startsWith(KAFKA_ATTR_PREFIX); - } - - private static Message buildBinaryMessageFromStructuredMap(Map structuredCloudEvent, - MessageHeaders originalHeaders) { - Object payload = structuredCloudEvent.remove(DATA); - if (payload == null) { - payload = Collections.emptyMap(); - } - - CloudEventMessageBuilder messageBuilder = CloudEventMessageBuilder - .withData(payload) - .copyHeaders(structuredCloudEvent); - - for (String key : originalHeaders.keySet()) { - if (!MessageHeaders.ID.equals(key)) { - messageBuilder.setHeader(key, originalHeaders.get(key)); - } - } - - return messageBuilder.build(); - } - - private static URI safeGetURI(Map map, String key) { - Object uri = map.get(key); - if (uri != null && uri instanceof String) { - uri = URI.create((String) uri); - } - return (URI) uri; - } - - public static class Protocols { - static String AMQP = "amqp"; - static String AVRO = "avro"; - static String HTTP = "http"; - static String JSON = "json"; - static String KAFKA = "kafka"; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionExtensionConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionExtensionConfiguration.java deleted file mode 100644 index 89a424c63..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionExtensionConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.function.core.FunctionInvocationHelper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; - -/** - * Configuration class with components relevant to Cloud Events support. - * - * @author Oleg Zhurakousky - * @since 3.1 - */ -@Configuration(proxyBeanMethods = false) -public class CloudEventsFunctionExtensionConfiguration { - - // The following two beans are intended to be mutually exclusive. Only one should be activated based - // on the presence of Cloud Event SDK API - @Bean - @ConditionalOnMissingBean - public FunctionInvocationHelper> nativeFunctionInvocationHelper(@Nullable CloudEventHeaderEnricher cloudEventHeadersProvider) { - return new CloudEventsFunctionInvocationHelper(cloudEventHeadersProvider); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionInvocationHelper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionInvocationHelper.java deleted file mode 100644 index 9d1b6fa2b..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent/CloudEventsFunctionInvocationHelper.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.net.URI; -import java.util.UUID; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.BeansException; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.cloud.function.core.FunctionInvocationHelper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Implementation of {@link FunctionInvocationHelper} to support Cloud Events. - * This is a primary (and the only) integration bridge with {@link FunctionInvocationWrapper}. - * - * @author Oleg Zhurakousky - * @since 3.1 - * - */ -public class CloudEventsFunctionInvocationHelper implements FunctionInvocationHelper>, ApplicationContextAware { - - private Log logger = LogFactory.getLog(this.getClass()); - - private ConfigurableApplicationContext applicationContext; - - private final CloudEventHeaderEnricher cloudEventAttributesProvider; - - private CompositeMessageConverter messageConverter; - - private final Class CLOUD_EVENT_CLASS; - - CloudEventsFunctionInvocationHelper(@Nullable CloudEventHeaderEnricher cloudEventHeadersProvider) { - this.cloudEventAttributesProvider = cloudEventHeadersProvider; - Class clazz = null; - try { - clazz = Thread.currentThread().getContextClassLoader().loadClass("io.cloudevents.CloudEvent"); - } - catch (Exception e) { - // ignore - } - CLOUD_EVENT_CLASS = clazz; - } - - @Override - public boolean isRetainOuputAsMessage(Message message) { - return message.getHeaders().containsKey(MessageUtils.TARGET_PROTOCOL) || (message.getHeaders().containsKey(MessageUtils.MESSAGE_TYPE) - && message.getHeaders().get(MessageUtils.MESSAGE_TYPE).equals(CloudEventMessageUtils.CLOUDEVENT_VALUE)); - } - - @Override - public Message preProcessInput(Message input, Object inputConverter) { - // TODO find a way to invoke it conditionally. May be check for certain headers with all known prefixes as well as content type - try { - return CloudEventMessageUtils.toCanonical(input, (MessageConverter) inputConverter); - } - catch (Exception e) { - return input; - } - } - - public void setMessageConverter(CompositeMessageConverter messageConverter) { - this.messageConverter = messageConverter; - } - - @Override - public Message postProcessResult(Object result, Message input) { - Object convertedResult = result; - if (this.messageConverter != null && CLOUD_EVENT_CLASS != null && CLOUD_EVENT_CLASS.isAssignableFrom(result.getClass())) { - convertedResult = this.messageConverter.toMessage(result, input.getHeaders()); - } - - String targetPrefix = CloudEventMessageUtils.DEFAULT_ATTR_PREFIX; - if (input != null) { - targetPrefix = CloudEventMessageUtils.determinePrefixToUse(input.getHeaders(), true); - } - else if (result instanceof Message) { - targetPrefix = CloudEventMessageUtils.determinePrefixToUse(((Message) result).getHeaders(), true); - } - - Assert.hasText(targetPrefix, "Unable to determine prefix for Cloud Event atttributes, " - + "which they must have according to protocol specification. Consider adding 'target-protocol' " - + "header with values of one of the supported protocols - [kafka, amqp, http]"); - if (logger.isDebugEnabled()) { - logger.debug("Cloud event attributes will be prefixed with '" + targetPrefix + "'"); - } - return this.doPostProcessResult(convertedResult, targetPrefix); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (ConfigurableApplicationContext) applicationContext; - } - - private Message doPostProcessResult(Object result, String targetPrefix) { - Message resultMessage = null; //result instanceof Message ? (Message) result : null; - CloudEventMessageBuilder messageBuilder; - if (result instanceof Message) { - if (CloudEventMessageUtils.isCloudEvent((Message) result)) { - messageBuilder = CloudEventMessageBuilder.fromMessage((Message) result); - } - else { - return (Message) result; - } - } - else { - messageBuilder = CloudEventMessageBuilder - .withData(result) - .setId(UUID.randomUUID().toString()) - .setSource(URI.create("http://spring.io/" + getApplicationName())) - .setType(result.getClass().getName()); - } - - if (this.cloudEventAttributesProvider != null) { - messageBuilder = this.cloudEventAttributesProvider.enrich(messageBuilder); - } - - resultMessage = messageBuilder.build(targetPrefix); - if (logger.isDebugEnabled()) { - logger.debug("Cloud Event result message: " + resultMessage); - } - return resultMessage; - } - - private String getApplicationName() { - ConfigurableEnvironment environment = this.applicationContext.getEnvironment(); - String name = environment.getProperty("spring.application.name"); - return (StringUtils.hasText(name) ? name : ""); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/DefaultMessageRoutingHandler.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/DefaultMessageRoutingHandler.java deleted file mode 100644 index 87c1b7ec7..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/DefaultMessageRoutingHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016-2022 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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.messaging.Message; - -/** - * Strategy for implementing a handler for un-routable messages. - * Works in parallel with {@link RoutingFunction}. When registered as a bean, RoutingFunction will not throw - * an exception if it can not route message and instead such message will be routed to this function. - * Its default implementation simply logs the un-routable event. - * Users are encouraged to provide their own implementation of this class. - * - * @author Oleg Zhurakousky - * @since 3.2.9 - * - */ -public class DefaultMessageRoutingHandler implements Consumer> { - - Log logger = LogFactory.getLog(DefaultMessageRoutingHandler.class); - - @Override - public void accept(Message message) { - if (logger.isDebugEnabled()) { - logger.debug("Route-to function can not be located in FunctionCatalog. Dropping unroutable message: " + message + ""); - } - else { - logger.warn("Route-to function can not be located in FunctionCatalog. Droping message"); - } - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionCatalog.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionCatalog.java deleted file mode 100644 index b8a84a8ef..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionCatalog.java +++ /dev/null @@ -1,100 +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.Set; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public interface FunctionCatalog { - - /** - * Will look up the instance of the functional interface by name only. - * - * @param functionDefinition the definition of the functional interface. Must - * not be null; - * @return instance of the functional interface registered with this catalog - */ - default T lookup(String functionDefinition) { - return this.lookup(null, functionDefinition, (String[]) null); - } - - /** - * Will look up the instance of the functional interface by name and type which - * can only be Supplier, Consumer or Function. If type is not provided, the - * lookup will be made based on name only. - * - * @param instance type - * @param type the type of functional interface. Can be null - * @param functionDefinition the definition of the functional interface. Must - * not be null; - * @return instance of the functional interface registered with this catalog - */ - default T lookup(Class type, String functionDefinition) { - return this.lookup(type, functionDefinition, (String[]) null); - } - - - /** - * Will look up the instance of the functional interface by name only. - * This lookup method assumes a very specific semantics which are: function sub-type(s) - * expected to be {@code Message}.
- * For example, - *

- * {@code Function, Message>} or - *
- * {@code Function>, Flux>>} or - *
- * {@code Consumer>>} etc. . . - *

- * The {@code acceptedOutputMimeTypes} are the string representation of {@link MimeType} where each - * mime-type in the provided array would correspond to the output with the same index - * (for cases of functions with multiple outputs) and is used to convert such output back - * to {@code Message}. - * If you need to provide several accepted types per specific output you can simply delimit - * them with comma (e.g., {@code application/json,text/plain...}). - * - * @param instance type which should be one of {@link Supplier}, {@link Function} or {@link Consumer}. - * @param functionDefinition the definition of a function (e.g., 'foo' or 'foo|bar') - * @param acceptedOutputMimeTypes acceptedOutputMimeTypes array of string representation of {@link MimeType}s - * used to convert function output back to {@code Message}. - * @return instance of the functional interface registered with this catalog - */ - default T lookup(String functionDefinition, String... expectedOutputMimeTypes) { - return this.lookup(null, functionDefinition, expectedOutputMimeTypes); - } - - T lookup(Class type, String functionDefinition, String... expectedOutputMimeTypes); - - Set getNames(Class type); - - /** - * Return the count of functions registered in this catalog. - * - * @return the count of functions registered in this catalog - */ - default int size() { - throw new UnsupportedOperationException("This instance of FunctionCatalog does not support this operation"); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java deleted file mode 100644 index efad20fb4..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionProperties.java +++ /dev/null @@ -1,232 +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.context; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.springframework.beans.BeansException; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.EnvironmentAware; -import org.springframework.core.env.Environment; -import org.springframework.util.CollectionUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.0 - * - */ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX) -public class FunctionProperties implements EnvironmentAware, ApplicationContextAware { - - /** - * The name prefix for properties defined by this properties class. - */ - public final static String PREFIX = "spring.cloud.function"; - - /** - * Name of the header to be used to instruct function to apply this content type for output conversion. - */ - public final static String EXPECT_CONTENT_TYPE_HEADER = "expected-content-type"; - - /** - * SpEL expression to be used with RoutingFunction. - */ - public final static String ROUTING_EXPRESSION = PREFIX + ".routing-expression"; - - /** - * The name of function definition property. - */ - public final static String FUNCTION_DEFINITION = PREFIX + ".definition"; - - /** - * Definition of the function to be used. This could be function name (e.g., 'myFunction') - * or function composition definition (e.g., 'myFunction|yourFunction') - */ - private String definition; - - /** - * SpEL expression which should result in function definition (e.g., function name or composition instruction). - * NOTE: SpEL evaluation context's root object is the input argument (e.g., Message). - */ - private String routingExpression; - - /** - * List of functions that are not eligible to be registered in Function Catalog. - */ - private final List ineligibleDefinitions; - - private Map configuration; - - private String expectedContentType; - - private Environment environment; - - private ApplicationContext applicationContext; - - public FunctionProperties() { - ineligibleDefinitions = new ArrayList<>(); - String[] definitions = new String[] { - "org.springframework.boot", - "org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration", - "org.springframework.cloud.function.context.config.FunctionsEndpointAutoConfiguration", - "classLoaderMetrics", - "jvmMemoryMetrics", - "jvmInfoMetrics", - "jvmCompilationMetrics", - "uptimeMetrics", - "kotlinToFunctionTransformer", - "CloudEventsMessageConverterConfiguration" - }; - ineligibleDefinitions.addAll(Arrays.asList(definitions)); - } - - public Map getConfiguration() { - return configuration; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void setConfiguration(Map configuration) { - for (Entry entry : configuration.entrySet()) { - String propertyX = "spring.cloud.function.configuration." + entry.getKey() + ".input-header-mapping-expression."; - String propertyY = "spring.cloud.function.configuration." + entry.getKey() + ".inputHeaderMappingExpression."; - Map headerMapping = entry.getValue().getInputHeaderMappingExpression(); - if (!CollectionUtils.isEmpty(headerMapping)) { - for (Object k : headerMapping.keySet()) { - if (this.environment.containsProperty(propertyX + k) || this.environment.containsProperty(propertyY + k)) { - Map current = entry.getValue().getInputHeaderMappingExpression(); - if (current.containsKey("0")) { - ((Map) current.get("0")).put(k, headerMapping.get(k)); - } - else { - entry.getValue().setInputHeaderMappingExpression(Collections.singletonMap("0", current)); - break; - } - } - } - } - propertyX = "spring.cloud.function.configuration." + entry.getKey() + ".output-header-mapping-expression."; - propertyY = "spring.cloud.function.configuration." + entry.getKey() + ".outputHeaderMappingExpression."; - headerMapping = entry.getValue().getOutputHeaderMappingExpression(); - if (!CollectionUtils.isEmpty(headerMapping)) { - for (Object k : headerMapping.keySet()) { - if (this.environment.containsProperty(propertyX + k) || this.environment.containsProperty(propertyY + k)) { - Map current = entry.getValue().getOutputHeaderMappingExpression(); - if (current.containsKey("0")) { - ((Map) current.get("0")).put(k, headerMapping.get(k)); - } - else { - entry.getValue().setOutputHeaderMappingExpression(Collections.singletonMap("0", current)); - break; - } - } - } - } - } - - this.configuration = configuration; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - public ApplicationContext getApplicationContext() { - return this.applicationContext; - } - - public String getDefinition() { - return definition; - } - - public void setDefinition(String definition) { - this.definition = definition; - } - - public String getRoutingExpression() { - return routingExpression; - } - - public void setRoutingExpression(String routingExpression) { - this.routingExpression = routingExpression; - } - - public String getExpectedContentType() { - return this.expectedContentType; - } - - public void setExpectedContentType(String expectedContentType) { - this.expectedContentType = expectedContentType; - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } - - public List getIneligibleDefinitions() { - return new ArrayList<>(this.ineligibleDefinitions); - } - - public void setIneligibleDefinitions(List definitions) { - this.ineligibleDefinitions.addAll(definitions); - } - - public static class FunctionConfigurationProperties { - - private Map inputHeaderMappingExpression; - - private Map outputHeaderMappingExpression; - - private boolean copyInputHeaders; - - public Map getInputHeaderMappingExpression() { - return inputHeaderMappingExpression; - } - - public void setInputHeaderMappingExpression(Map inputHeaderMappingExpression) { - this.inputHeaderMappingExpression = inputHeaderMappingExpression; - } - - public Map getOutputHeaderMappingExpression() { - return outputHeaderMappingExpression; - } - - public void setOutputHeaderMappingExpression( - Map outputHeaderMappingExpression) { - this.outputHeaderMappingExpression = outputHeaderMappingExpression; - } - - public boolean isCopyInputHeaders() { - return copyInputHeaders; - } - - public void setCopyInputHeaders(boolean copyInputHeaders) { - this.copyInputHeaders = copyInputHeaders; - } - - } -} 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 deleted file mode 100644 index 6e3b3666b..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2016-2023 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.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration; -import org.springframework.core.KotlinDetector; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -/** - * @param target type - * @author Dave Syer - * @author Oleg Zhurakousky - * @author Soby Chacko - */ -public class FunctionRegistration implements BeanNameAware { - - /** - * Suffix used to add to the name of FunctionRegistration bean that - * corresponds to the an actual function bean. It is often used when - * the actual function bean may not be a java Function (e.g., Kotlin) - * and certain custom wrapping is required. - *
- * NOTE: This is not intended as oublis API - */ - public static String REGISTRATION_NAME_SUFFIX = "_registration"; - - private final Set names = new LinkedHashSet<>(); - - private final Map properties = new LinkedHashMap<>(); - - private T target; - - private Type type; - - /** - * In certain cased, {@link FunctionRegistration} needs to know details - * about the user function. For example, when the user provides a BiConsumer, - * we wrap that in a regular Function. There are actions that a downstream client - * needs to take based on the type information of the wrapped function such as - * not creating an output binding when the wrapped type is a BiConsumer. - */ - private Object userFunction; - - /** - * Creates instance of FunctionRegistration. - * @param target instance of {@link Supplier}, {@link Function} or {@link Consumer} - * @param names additional set of names for this registration. Additional names can be - * provided {@link #name(String)} or {@link #names(String...)} operations. - */ - public FunctionRegistration(T target, String... names) { - Assert.notNull(target, "'target' must not be null"); - this.target = target; - this.names(names); - } - - public Map getProperties() { - return this.properties; - } - - public Set getNames() { - return this.names; - } - - /** - * Will set the names for this registration clearing all previous names first. If you - * want to add a name or set or names to the existing set of names use - * {@link #names(Collection)} or {@link #name(String)} or {@link #names(String...)} - * operations. - * @param names - bean names - */ - public void setNames(Set names) { - this.names.clear(); - this.names.addAll(names); - } - - public Type getType() { - return this.type; - } - - public T getTarget() { - return this.target; - } - - public FunctionRegistration properties(Map properties) { - this.properties.putAll(properties); - return this; - } - - public FunctionRegistration type(Type type) { - this.type = type; - if (KotlinDetector.isKotlinPresent() && this.target instanceof KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper) { - return this; - } - Type discoveredFunctionType = FunctionTypeUtils.discoverFunctionTypeFromClass(this.target.getClass()); - if (discoveredFunctionType == null) { // only valid for Kafka Stream KStream[] return type. - return null; - } - - 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; - } - - /** - * Allows to override the target of this registration with a new target that typically - * wraps the original target. This typically happens when original target is wrapped - * into its {@link Flux} counterpart (e.g., Function into FluxFunction) - * @param target new target - * @return this registration with new target - */ - public FunctionRegistration target(T target) { - this.target = target; - return this; - } - - public FunctionRegistration name(String name) { - return this.names(name); - } - - public FunctionRegistration names(Collection names) { - this.names.addAll(names); - return this; - } - - public FunctionRegistration names(String... names) { - return this.names(Arrays.asList(names)); - } - - /** - * Transforms (wraps) function identified by the 'target' to its {@code Flux} - * equivalent unless it already is. For example, {@code Function} - * becomes {@code Function, Flux>} - * @param the expected target type of the function (e.g., FluxFunction) - * @return {@code FunctionRegistration} with the appropriately wrapped target. - * - */ - - @Override - public void setBeanName(String name) { - if (CollectionUtils.isEmpty(this.names)) { - this.name(name); - } - } - - public Object getUserFunction() { - return userFunction; - } - - public void setUserFunction(Object userFunction) { - this.userFunction = userFunction; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistry.java deleted file mode 100644 index 6770a8196..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistry.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.context; - -/** - * @author Dave Syer - * - */ -public interface FunctionRegistry extends FunctionCatalog { - - void register(FunctionRegistration registration); - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionTypeProcessor.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionTypeProcessor.java deleted file mode 100644 index 67349fc9a..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionTypeProcessor.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2019-2022 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.HashSet; -import java.util.Set; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.springframework.aot.generate.GenerationContext; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; -import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; -import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.cloud.function.context.message.MessageUtils; - -/** - * Ensure that Function/Consumer input types are reflectively available. - * - * @author Oleg Zhurakousky - */ -public class FunctionTypeProcessor implements BeanFactoryInitializationAotProcessor { - - @Override - public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { - Set> typeHints = new HashSet<>(); - - String[] names = beanFactory.getBeanDefinitionNames(); - for (int i = 0; i < names.length; i++) { - String beanName = names[i]; - Class beanClass = beanFactory.getType(beanName); - if (this.isFunction(beanClass)) { - Type functionType = FunctionTypeUtils.discoverFunctionTypeFromClass(beanClass); - - if (!(functionType instanceof ParameterizedType)) { - functionType = FunctionContextUtils.findType(beanFactory, beanName); - } - this.registerAllGenericTypes((ParameterizedType) functionType, typeHints); - } - } - return new ReflectiveProcessorBeanFactoryInitializationAotContribution(typeHints.toArray(Class[]::new)); - } - - private void registerAllGenericTypes(ParameterizedType type, Set> typeHints) { - Type[] types = type.getActualTypeArguments(); - for (int i = 0; i < types.length; i++) { - Type functionParameterType = types[i]; - String name = functionParameterType.getTypeName(); - if (!isCoreJavaType(name)) { - typeHints.add(FunctionTypeUtils.getRawType(functionParameterType)); - } - if (functionParameterType instanceof ParameterizedType) { - this.registerAllGenericTypes((ParameterizedType) functionParameterType, typeHints); - } - } - } - - private boolean isCoreJavaType(String className) { - return className.startsWith("java.") || className.startsWith("javax."); - } - - private boolean isFunction(Class beanType) { - return Function.class.isAssignableFrom(beanType) - || Consumer.class.isAssignableFrom(beanType) - || Supplier.class.isAssignableFrom(beanType); - } - - private static final class ReflectiveProcessorBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution { - - private final Class[] typeHints; - - private ReflectiveProcessorBeanFactoryInitializationAotContribution(Class[] typeHints) { - this.typeHints = typeHints; - } - - @Override - public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) { - RuntimeHints runtimeHints = generationContext.getRuntimeHints(); - for (int i = 0; i < typeHints.length; i++) { - runtimeHints.reflection().registerType(typeHints[i], MemberCategory.PUBLIC_FIELDS, - MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - } - - // known static types - runtimeHints.reflection().registerType(MessageUtils.MessageStructureWithCaseInsensitiveHeaderKeys.class, - MemberCategory.INVOKE_PUBLIC_METHODS); - } - - } -} 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 deleted file mode 100644 index 9c01b78df..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionalSpringApplication.java +++ /dev/null @@ -1,192 +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.context; - -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 org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.ApplicationContextFactory; -import org.springframework.boot.WebApplicationType; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.ObjectUtils; - -import static java.util.Arrays.stream; - -/** - * @author Dave Syer - * @author Semyon Fishman - * @author Oleg Zhurakousky - */ -public class FunctionalSpringApplication - extends org.springframework.boot.SpringApplication { - - /** - * Flag to say that context is functional beans. - */ - public static final String SPRING_FUNCTIONAL_ENABLED = "spring.functional.enabled"; - - /** - * Enumeration of web application types. - */ - public static final String SPRING_WEB_APPLICATION_TYPE = "spring.main.web-application-type"; - - /** - * Name of default property source. - */ - private static final String DEFAULT_PROPERTIES = "defaultProperties"; - - public FunctionalSpringApplication(Class... primarySources) { - super(primarySources); - setApplicationContextFactory(ApplicationContextFactory.ofContextClass(GenericApplicationContext.class)); - if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", - null)) { - setWebApplicationType(WebApplicationType.REACTIVE); - } - else { - setWebApplicationType(WebApplicationType.NONE); - } - } - - public static void main(String[] args) throws Exception { - FunctionalSpringApplication.run(new Class[0], args); - } - - public static ConfigurableApplicationContext run(Class primarySource, - String... args) { - return run(new Class[] { primarySource }, args); - } - - public static ConfigurableApplicationContext run(Class[] primarySources, - String[] args) { - return new FunctionalSpringApplication(primarySources).run(args); - } - - @SuppressWarnings("unchecked") - @Override - protected void postProcessApplicationContext(ConfigurableApplicationContext context) { - super.postProcessApplicationContext(context); - boolean functional = false; - Assert.isInstanceOf(GenericApplicationContext.class, context, - "ApplicationContext must be an instanceof GenericApplicationContext"); - for (Object source : getAllSources()) { - System.out.println("======> SOURCE: " + source); - Class type = null; - Object handler = null; - if (source instanceof String) { - String name = (String) source; - if (ClassUtils.isPresent(name, null)) { - type = ClassUtils.resolveClassName(name, null); - } - } - else if (source instanceof Class) { - type = (Class) source; - } - else { - type = source.getClass(); - handler = source; - } - if (ApplicationContextInitializer.class.isAssignableFrom(type)) { - if (handler == null) { - handler = BeanUtils.instantiateClass(type); - } - - ApplicationContextInitializer initializer = - (ApplicationContextInitializer) handler; - initializer.initialize(context); - functional = true; - } - else if (Function.class.isAssignableFrom(type) - || Consumer.class.isAssignableFrom(type) - || Supplier.class.isAssignableFrom(type)) { - Class functionType = type; - Object function = handler; - if (source.equals(functionType)) { - context.addBeanFactoryPostProcessor(beanFactory -> { - BeanDefinitionRegistry bdRegistry = (BeanDefinitionRegistry) beanFactory; - if (!ObjectUtils.isEmpty(context.getBeanNamesForType(functionType))) { - stream(context.getBeanNamesForType(functionType)) - .forEach(beanName -> bdRegistry.registerAlias(beanName, "function")); - } - else { - this.register((GenericApplicationContext) context, function, functionType); - } - }); - } - else { - this.register((GenericApplicationContext) context, function, functionType); - } - functional = true; - } - } - if (functional) { - defaultProperties(context); - } - } - - private void register(GenericApplicationContext context, Object function, Class functionType) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>( - handler(context, function, functionType)) - .type(functionType)); - } - - private Object handler(GenericApplicationContext generic, Object handler, - Class type) { - if (handler == null) { - handler = generic.getAutowireCapableBeanFactory().createBean(type); - } - return handler; - } - - @Override - protected void load(ApplicationContext context, Object[] sources) { - if (!context.getEnvironment().getProperty(SPRING_FUNCTIONAL_ENABLED, - Boolean.class, false)) { - super.load(context, sources); - } - } - - private void defaultProperties(ConfigurableApplicationContext context) { - MutablePropertySources sources = context.getEnvironment().getPropertySources(); - if (!sources.contains(DEFAULT_PROPERTIES)) { - sources.addLast( - new MapPropertySource(DEFAULT_PROPERTIES, Collections.emptyMap())); - } - @SuppressWarnings("unchecked") - Map source = (Map) sources.get(DEFAULT_PROPERTIES) - .getSource(); - Map map = new HashMap<>(source); - map.put(SPRING_FUNCTIONAL_ENABLED, "true"); - map.put(SPRING_WEB_APPLICATION_TYPE, getWebApplicationType()); - sources.replace(DEFAULT_PROPERTIES, - new MapPropertySource(DEFAULT_PROPERTIES, map)); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/MessageRoutingCallback.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/MessageRoutingCallback.java deleted file mode 100644 index 2ba6000f3..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/MessageRoutingCallback.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021-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.context; - -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.messaging.Message; - -/** - * Java-based strategy to assist with determining the name of the route-to function definition. - * Once implementation is registered as a bean in application context - * it will be picked up by the {@link RoutingFunction}. - * - * While {@link RoutingFunction} provides several mechanisms to determine the route-to function definition - * this callback takes precedence over all of them. - * - * @author Oleg Zhurakousky - * @since 3.1 - */ -public interface MessageRoutingCallback { - - /** - * Computes and returns the instance of {@link FunctionRoutingResult} which encapsulates, - * at the very minimum, function definition. - *

- * Providing such message is primarily an optimization feature. It could be useful for cases - * where routing procedure is complex and results in, let's say, conversion of the payload to - * the target type, which would effectively be thrown away if the ability to modify the target - * message for downstream use didn't exist, resulting in repeated transformation, type conversion etc. - * - * @param message input message - * @return instance of {@link FunctionRoutingResult} containing the result of the routing computation - */ - default String routingResult(Message message) { - return (String) message.getHeaders().get(FunctionProperties.FUNCTION_DEFINITION); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PollableBean.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PollableBean.java deleted file mode 100644 index 5994cd7f4..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PollableBean.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; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.function.Supplier; - -import org.springframework.context.annotation.Bean; - -/** - * - * A marker and qualifier annotation to signal that - * annotated functional factory method is a bean (e.g., Supplier, Function or Consumer) - * that also needs to be polled periodically. - *
- * This has special significance to the reactive suppliers (e.g., {@code Supplier>}), - * since by default they are treated as producers of an infinite stream. - * However if such suppliers produce a finite stream they may need to be triggered again. - *
- *
- * NOTE: The spring-cloud-function framework provides no default post processing behavior for this annotation. This - * means that annotating a factory method with this annotation will not have any effect without some application/framework - * specific post processing (see spring-cloud-stream as an example). - * - * - * @author Oleg Zhurakousky - * @since 3.0 - * - */ -@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Bean -@Documented -public @interface PollableBean { - - /** - * Signals to the post processors of this annotation that the result produced by the - * annotated {@link Supplier} has to be split. Specifics on how to split and what - * to split are left to the underlying framework. - * - * @return true if the resulting stream produced by the - * annotated {@link Supplier} has to be split. - */ - boolean splittable() default true; -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PostProcessingFunction.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PostProcessingFunction.java deleted file mode 100644 index 5c5d1d23c..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/PostProcessingFunction.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2023-2023 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.springframework.messaging.Message; - -/** - * Strategy for implementing function with post processing behavior. - *
- * The core framework only provides support for the post-processing behavior. - * The actual invocation of post-processing is left to the end user or the framework which - * integrates Spring Cloud Function. This is because post-processing can mean different things - * in different execution contexts. See {@link #postProcess(Message)} method for more information. - * - * @param - input type - * @param - output type - * - * @author Oleg Zhurakousky - * @since 4.0.3 - * - */ -public interface PostProcessingFunction extends Function { - - @SuppressWarnings("unchecked") - @Override - default O apply(I t) { - return (O) t; - } - - /** - * Will post process the result of this's function invocation after this function has been triggered. - *
- * This operation is not managed/invoked by the core functionality of the Spring Cloud Function. - * It is specifically designed as a hook for other frameworks and extensions to invoke after - * this function was "triggered" and there is a requirement to do some post processing. The word "triggered" - * can mean different things in different execution contexts. For example, in spring-cloud-stream it means - * that the function has been invoked and the result of the function has been sent to the target destination. - * - * The boolean value argument - 'success' - allows the triggering framework to signal success or - * failure of its triggering operation whatever that may mean. - * - * @param result - the result of function invocation as an instance of {@link Message} including all the metadata as message headers. - */ - default void postProcess(Message result) { - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java deleted file mode 100644 index 31fa6e41f..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2019-2023 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.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.core.FunctionInvocationHelper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.KotlinDetector; -import org.springframework.core.ResolvableType; -import org.springframework.core.convert.ConversionService; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * Implementation of {@link FunctionRegistry} capable of discovering functions in {@link BeanFactory}. - * - * @author Oleg Zhurakousky - * @author Soby Chacko - */ -public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry implements ApplicationContextAware { - - private GenericApplicationContext applicationContext; - - public BeanFactoryAwareFunctionRegistry(ConversionService conversionService, CompositeMessageConverter messageConverter, - JsonMapper jsonMapper, @Nullable FunctionProperties functionProperties, @Nullable FunctionInvocationHelper> functionInvocationHelper) { - super(conversionService, messageConverter, jsonMapper, functionProperties, functionInvocationHelper); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (GenericApplicationContext) applicationContext; - } - - /* - * Basically gives an approximation only including function registrations and SFC. - * Excludes possible POJOs that can be treated as functions - */ - @Override - public int size() { - return this.applicationContext.getBeanNamesForType(Supplier.class).length + - this.applicationContext.getBeanNamesForType(Function.class).length + - this.applicationContext.getBeanNamesForType(Consumer.class).length + - super.size(); - } - - /* - * Doesn't account for POJO so we really don't know until it's been lookedup - */ - @Override - public Set getNames(Class type) { - Set registeredNames = super.getNames(type); - if (type == null) { - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(Function.class))); - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(Supplier.class))); - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(Consumer.class))); - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(BiFunction.class))); - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(BiConsumer.class))); - registeredNames - .addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(FunctionRegistration.class))); - } - else { - registeredNames.addAll(Arrays.asList(this.applicationContext.getBeanNamesForType(type))); - } - return registeredNames; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public T lookup(Class type, String functionDefinition, String... expectedOutputMimeTypes) { - functionDefinition = StringUtils.hasText(functionDefinition) - ? functionDefinition - : this.applicationContext.getEnvironment().getProperty(FunctionProperties.FUNCTION_DEFINITION, ""); - if (!this.applicationContext.containsBean(functionDefinition) || !KotlinDetector.isKotlinType(this.applicationContext.getBean(functionDefinition).getClass())) { - functionDefinition = this.normalizeFunctionDefinition(functionDefinition); - } - if (!StringUtils.hasText(functionDefinition)) { - Collection functionalBeans = this.getNames(null).stream() - .filter(name -> !RoutingFunction.FUNCTION_NAME.equals(name)) - .filter(name -> !RoutingFunction.DEFAULT_ROUTE_HANDLER.equals(name)) - .collect(Collectors.toList()); - if (!CollectionUtils.isEmpty(functionalBeans) && functionalBeans.size() > 1) { - logger.warn("Multiple functional beans were found " + functionalBeans + ", thus can't determine default function definition. Please " - + "use 'spring.cloud.function.definition' property to explicitly define it. "); - } - } - if (!isFunctionDefinitionEligible(functionDefinition)) { - return null; - } - FunctionInvocationWrapper function = this.doLookup(type, functionDefinition, expectedOutputMimeTypes); - Object syncInstance = functionDefinition == null ? this : functionDefinition; - synchronized (syncInstance) { - if (function == null) { - Set functionRegistratioinNames = super.getNames(null); - String[] functionNames = StringUtils.delimitedListToStringArray(functionDefinition.replaceAll(",", "|").trim(), "|"); - for (String functionName : functionNames) { - if (functionRegistratioinNames.contains(functionName) && logger.isDebugEnabled()) { - logger.debug("Skipping function '" + functionName + "' since it is already present"); - } - else { - Object functionCandidate = this.discoverFunctionInBeanFactory(functionName); - if (functionCandidate != null) { - Type functionType = null; - FunctionRegistration functionRegistration = null; - if (functionCandidate instanceof FunctionRegistration) { - functionRegistration = (FunctionRegistration) functionCandidate; - } - else if (functionCandidate instanceof BiFunction || functionCandidate instanceof BiConsumer) { - functionRegistration = this.registerMessagingBiFunction(functionCandidate, functionName); - } - else if (KotlinDetector.isKotlinType(functionCandidate.getClass())) { - KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper wrapper = - new KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper(functionCandidate); - wrapper.setName(functionName); - wrapper.setBeanFactory(this.applicationContext.getBeanFactory()); - functionRegistration = wrapper.getFunctionRegistration(); - } - else if (this.isFunctionPojo(functionCandidate, functionName)) { - Method functionalMethod = FunctionTypeUtils.discoverFunctionalMethod(functionCandidate.getClass()); - functionCandidate = this.proxyTarget(functionCandidate, functionalMethod); - functionType = FunctionTypeUtils.fromFunctionMethod(functionalMethod); - } - else if (this.isSpecialFunctionRegistration(functionNames, functionName)) { - functionRegistration = this.applicationContext - .getBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, FunctionRegistration.class); - } - else { - functionType = FunctionTypeUtils.discoverFunctionType(functionCandidate, functionName, this.applicationContext); - } - if (functionRegistration == null) { - functionRegistration = new FunctionRegistration(functionCandidate, functionName).type(functionType); - } - // Certain Kafka Streams functions such as KStream[] return types could be null (esp when using Kotlin). - this.register(functionRegistration); - } - else { - if (logger.isDebugEnabled()) { - logger.debug("Function '" + functionName + "' is not available in FunctionCatalog or BeanFactory"); - } - } - } - } - function = super.doLookup(type, functionDefinition, expectedOutputMimeTypes); - } - } - - return (T) function; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private FunctionRegistration registerMessagingBiFunction(Object userFunction, String functionName) { - Type biFunctionType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), functionName); - Type inputType1 = Object.class; - Type inputType2 = Object.class; - if (biFunctionType instanceof ParameterizedType) { - inputType1 = ((ParameterizedType) biFunctionType).getActualTypeArguments()[0]; - inputType2 = ((ParameterizedType) biFunctionType).getActualTypeArguments()[1]; - } - - if (!FunctionTypeUtils.isTypeMap(inputType2)) { - logger.debug("BiFunction's second argument must be assignable to Map, since BiFunction " - + "represents parsed Message with first argument being payload and second headers. " - + "Other signatures are not supported at the moment."); - } - - ResolvableType messageType = ResolvableType.forClassWithGenerics(Message.class, ResolvableType.forType(inputType1)); - Type biFunctionWrapperType = ResolvableType.forClassWithGenerics(Function.class, messageType, ResolvableType.forType(inputType2)).getType(); - - Function wrapperFunction = message -> { - Object payload = ((Message) message).getPayload(); - if (payload.getClass().getName().equals("org.springframework.kafka.support.KafkaNull")) { - payload = null; - } - if (userFunction instanceof BiConsumer) { - ((BiConsumer) userFunction).accept(payload, ((Message) message).getHeaders()); - return null; - } - else { - return ((BiFunction) userFunction).apply(payload, ((Message) message).getHeaders()); - } - }; - - FunctionRegistration functionRegistration = new FunctionRegistration<>(wrapperFunction, functionName).type(biFunctionWrapperType); - functionRegistration.setUserFunction(userFunction); - return functionRegistration; - } - - private Object discoverFunctionInBeanFactory(String functionName) { - Object functionCandidate = null; - if (this.applicationContext.containsBean(functionName)) { - functionCandidate = this.applicationContext.getBean(functionName); - } - else { - try { - functionCandidate = BeanFactoryAnnotationUtils.qualifiedBeanOfType(this.applicationContext.getBeanFactory(), Object.class, functionName); - } - catch (Exception e) { - // ignore since there is no safe isAvailable-kind of method - } - } - return functionCandidate; - } - - @Override - protected boolean containsFunction(String functionName) { - return super.containsFunction(functionName) || this.applicationContext.containsBean(functionName); - } - - private boolean isFunctionPojo(Object functionCandidate, String functionName) { - return !functionCandidate.getClass().isSynthetic() - && !(functionCandidate instanceof Supplier) - && !(functionCandidate instanceof Function) - && !(functionCandidate instanceof Consumer) - && !this.applicationContext.containsBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX); - } - - /** - * At the moment 'special function registration' simply implies that a bean under the provided functionName - * may have already been wrapped and registered as FunuctionRegistration with BeanFactory under the name of - * the function suffixed with {@link FunctionRegistration#REGISTRATION_NAME_SUFFIX} - * (e.g., 'myKotlinFunction_registration'). - *

- * At the moment only Kotlin module does this - * - * @param functionCandidate candidate for FunctionInvocationWrapper instance - * @param functionName the name of the function - * @return true if this function candidate qualifies - */ - private boolean isSpecialFunctionRegistration(Object functionCandidate, String functionName) { - return this.applicationContext.containsBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX); - } - - private Object proxyTarget(Object targetFunction, Method actualMethodToCall) { - ProxyFactory pf = new ProxyFactory(targetFunction); - pf.setProxyTargetClass(true); - pf.setInterfaces(Function.class); - pf.addAdvice(new MethodInterceptor() { - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - return actualMethodToCall.invoke(invocation.getThis(), invocation.getArguments()); - } - }); - return pf.getProxy(); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionAroundWrapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionAroundWrapper.java deleted file mode 100644 index d656420d9..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionAroundWrapper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2020-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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; - -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; -import org.springframework.util.StringUtils; - -/** - * Wrapper that acts as around advise over function invocation. - * If registered as bean it will be autowired into {@link FunctionInvocationWrapper}. - * Keep in mind that it only affects imperative invocations where input is {@link Message} - * - * NOTE: This API is experimental and and could change without notice. It is - * intended for internal use only (e.g., spring-cloud-sleuth) - * - * @author Oleg Zhurakousky - * @since 3.1 - */ -public abstract class FunctionAroundWrapper { - - private static final Log log = LogFactory.getLog(FunctionAroundWrapper.class); - - public final Object apply(Object input, FunctionInvocationWrapper targetFunction) { - String functionalTracingEnabledStr = System.getProperty("spring.cloud.function.observability.enabled"); - boolean functionalTracingEnabled = !StringUtils.hasText(functionalTracingEnabledStr) - || Boolean.parseBoolean(functionalTracingEnabledStr); - if (functionalTracingEnabled && !(input instanceof Publisher) && input instanceof Message && !FunctionTypeUtils.isCollectionOfMessage(targetFunction.getOutputType())) { - return this.doApply(input, targetFunction); - } - else { - return targetFunction.apply(input); - } - } - - protected abstract Object doApply(Object input, FunctionInvocationWrapper targetFunction); -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionCatalogEvent.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionCatalogEvent.java deleted file mode 100644 index 8ac2bfefb..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionCatalogEvent.java +++ /dev/null @@ -1,32 +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.catalog; - -import org.springframework.context.ApplicationEvent; - -/** - * @author Dave Syer - * - */ -@SuppressWarnings("serial") -public class FunctionCatalogEvent extends ApplicationEvent { - - public FunctionCatalogEvent(Object source) { - super(source); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionRegistrationEvent.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionRegistrationEvent.java deleted file mode 100644 index 63b18af2f..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionRegistrationEvent.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.context.catalog; - -import java.util.HashSet; -import java.util.Set; - -/** - * @author Dave Syer - * - */ -@SuppressWarnings("serial") -public class FunctionRegistrationEvent extends FunctionCatalogEvent { - - private final Class type; - - private final Set names; - - public FunctionRegistrationEvent(Object source, Class type, Set names) { - super(source); - this.type = type; - this.names = new HashSet<>(names); - } - - public Class getType() { - return this.type; - } - - public Set getNames() { - return this.names; - } - -} 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 deleted file mode 100644 index 24e181e12..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright 2019-2022 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.GenericArrayType; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.JsonNode; -import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; -import net.jodah.typetools.TypeResolver; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -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.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.KotlinDetector; -import org.springframework.core.ResolvableType; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - - - -/** - * Set of utility operations to interrogate function definitions. - * - * @author Oleg Zhurakousky - * @author Andrey Shlykov - * - * @since 3.0 - */ -public final class FunctionTypeUtils { - - private static Log logger = LogFactory.getLog(FunctionTypeUtils.class); - - private 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, - * If provided type is {@code Message>} this operation will return 'true'. - * - * @param type type to interrogate - * @return 'true' if this type represents a {@link Collection}. Otherwise 'false'. - */ - public static boolean isTypeCollection(Type type) { - if (Collection.class.isAssignableFrom(getRawType(type))) { - return true; - } - type = getGenericType(type); - type = type == null ? Object.class : type; - Class rawType = type instanceof ParameterizedType ? getRawType(type) : (Class) type; - return Collection.class.isAssignableFrom(rawType) || JsonNode.class.isAssignableFrom(rawType); - } - - public static boolean isTypeMap(Type type) { - if (Map.class.isAssignableFrom(getRawType(type))) { - return true; - } - type = getGenericType(type); - Class rawType = type instanceof ParameterizedType ? getRawType(type) : (Class) type; - return Map.class.isAssignableFrom(rawType); - } - - public static boolean isTypeArray(Type type) { - return getRawType(type).isArray(); - } - - public static boolean isJsonNode(Type type) { - return getRawType(type).isArray(); - } - - /** - * A convenience method identical to {@link #getImmediateGenericType(Type, int)} - * for cases when provided 'type' is {@link Publisher} or {@link Message}. - * - * @param type type to interrogate - * @return generic type if possible otherwise the same type as provided - */ - public static Type getGenericType(Type type) { - if (isPublisher(type) || isMessage(type)) { - type = getImmediateGenericType(type, 0); - } - - return TypeResolver.reify(type instanceof GenericArrayType ? type : TypeResolver.reify(type)); - } - - /** - * Effectively converts {@link Type} which could be {@link ParameterizedType} to raw Class (no generics). - * @param type actual {@link Type} instance - * @return instance of {@link Class} as raw representation of the provided {@link Type} - */ - public static Class getRawType(Type type) { - return type != null ? TypeResolver - .resolveRawClass(type instanceof GenericArrayType ? type : TypeResolver.reify(type), null) : null; - } - - /** - * Will attempt to discover functional methods on the class. It's applicable for POJOs as well as - * functional classes in `java.util.function` package. For the later the names of the methods are - * well known (`apply`, `accept` and `get`). For the former it will attempt to discover a single method - * following semantics described in (see {@link FunctionalInterface}) - * - * @param pojoFunctionClass the class to introspect - * @return functional method - */ - public static Method discoverFunctionalMethod(Class pojoFunctionClass) { - if (Supplier.class.isAssignableFrom(pojoFunctionClass)) { - return Stream.of(ReflectionUtils.getDeclaredMethods(pojoFunctionClass)).filter(m -> !m.isSynthetic() - && m.getName().equals("get")).findFirst().get(); - } - else if (Consumer.class.isAssignableFrom(pojoFunctionClass) || BiConsumer.class.isAssignableFrom(pojoFunctionClass)) { - return Stream.of(ReflectionUtils.getDeclaredMethods(pojoFunctionClass)).filter(m -> !m.isSynthetic() - && m.getName().equals("accept")).findFirst().get(); - } - else if (Function.class.isAssignableFrom(pojoFunctionClass) || BiFunction.class.isAssignableFrom(pojoFunctionClass)) { - return Stream.of(ReflectionUtils.getDeclaredMethods(pojoFunctionClass)).filter(m -> !m.isSynthetic() - && m.getName().equals("apply")).findFirst().get(); - } - - List methods = new ArrayList<>(); - ReflectionUtils.doWithMethods(pojoFunctionClass, method -> { - if (method.getDeclaringClass() == pojoFunctionClass) { - methods.add(method); - } - - }, method -> - !method.getDeclaringClass().isAssignableFrom(Object.class) - && !method.isSynthetic() && !method.isBridge() && !method.isVarArgs()); - - Assert.isTrue(methods.size() == 1, "Discovered " + methods.size() + " methods that would qualify as 'functional' - " - + methods + ".\n Class '" + pojoFunctionClass + "' is not a FunctionalInterface."); - - return methods.get(0); - } - - @SuppressWarnings("unchecked") - public static Type discoverFunctionTypeFromClass(Class functionalClass) { - if (KotlinDetector.isKotlinPresent()) { - if (Function1.class.isAssignableFrom(functionalClass)) { - return TypeResolver.reify(Function1.class, (Class>) functionalClass); - } - else if (Function0.class.isAssignableFrom(functionalClass)) { - return TypeResolver.reify(Function0.class, (Class>) functionalClass); - } - } - if (Function.class.isAssignableFrom(functionalClass)) { - for (Type superInterface : functionalClass.getGenericInterfaces()) { - if (superInterface != null && !superInterface.equals(Object.class)) { - if (superInterface.toString().contains("KStream") && ResolvableType.forType(superInterface).getGeneric(1).isArray()) { - return null; - } - } - } - return TypeResolver.reify(Function.class, (Class>) functionalClass); - } - else if (Consumer.class.isAssignableFrom(functionalClass)) { - return TypeResolver.reify(Consumer.class, (Class>) functionalClass); - } - else if (Supplier.class.isAssignableFrom(functionalClass)) { - return TypeResolver.reify(Supplier.class, (Class>) functionalClass); - } - return TypeResolver.reify(functionalClass); - } - - /** - * 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") || - functionMethod.getName().equals("accept") || - functionMethod.getName().equals("get"), - "Only Supplier, Function or Consumer supported at the moment. Was " + functionMethod.getDeclaringClass()); - - if (functionMethod.getName().equals("apply")) { - return ResolvableType.forClassWithGenerics(Function.class, - ResolvableType.forMethodParameter(functionMethod, 0), - ResolvableType.forMethodReturnType(functionMethod)).getType(); - - } - else if (functionMethod.getName().equals("accept")) { - return ResolvableType.forClassWithGenerics(Consumer.class, - ResolvableType.forMethodParameter(functionMethod, 0)).getType(); - } - else { - return ResolvableType.forClassWithGenerics(Supplier.class, - ResolvableType.forMethodReturnType(functionMethod)).getType(); - } - } - - public static int getInputCount(FunctionInvocationWrapper function) { - int inputCount = function.isSupplier() ? 0 : 1; - if (inputCount > 0) { - Type inputType = function.getInputType(); - if (isMulti(inputType)) { - inputCount = ((ParameterizedType) inputType).getActualTypeArguments().length; - } - } - return inputCount; - } - - public static int getOutputCount(FunctionInvocationWrapper function) { - int outputCount = function.isConsumer() ? 0 : 1; - if (outputCount > 0) { - Type outputType = function.getOutputType(); - if (isMulti(outputType)) { - outputCount = ((ParameterizedType) outputType).getActualTypeArguments().length; - } - } - 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 - * @return the input type as {@link Type} - */ - @SuppressWarnings("unchecked") - public static Type getInputType(Type functionType) { - if (isSupplier(functionType)) { - logger.debug("Supplier does not have input type, returning null as input type."); - return null; - } - assertSupportedTypes(functionType); - - Type inputType; - if (functionType instanceof Class) { - functionType = Function.class.isAssignableFrom((Class) functionType) - ? TypeResolver.reify(Function.class, (Class>) functionType) - : TypeResolver.reify(Consumer.class, (Class>) functionType); - } - - inputType = functionType instanceof ParameterizedType - ? ((ParameterizedType) functionType).getActualTypeArguments()[0] - : Object.class; - - return inputType; - } - - @SuppressWarnings("rawtypes") - public static Type discoverFunctionType(Object function, String functionName, GenericApplicationContext applicationContext) { - if (function instanceof RoutingFunction) { - return FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionName); - } - else if (function instanceof FunctionRegistration) { - 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(); - } - - boolean beanDefinitionExists = false; - String functionBeanDefinitionName = discoverDefinitionName(functionName, applicationContext); - beanDefinitionExists = applicationContext.getBeanFactory().containsBeanDefinition(functionBeanDefinitionName); - if (applicationContext.containsBean("&" + functionName)) { - Class objectType = applicationContext.getBean("&" + functionName, FactoryBean.class) - .getObjectType(); - return FunctionTypeUtils.discoverFunctionTypeFromClass(objectType); - } - - Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(function.getClass()); - if (beanDefinitionExists) { - Type t = FunctionTypeUtils.getImmediateGenericType(type, 0); - if (t == null || t == Object.class) { - type = FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionBeanDefinitionName); - } - } - else if (!(type instanceof ParameterizedType)) { - String beanDefinitionName = discoverBeanDefinitionNameByQualifier(applicationContext.getBeanFactory(), functionName); - if (StringUtils.hasText(beanDefinitionName)) { - type = FunctionContextUtils.findType(applicationContext.getBeanFactory(), beanDefinitionName); - } - } - return type; - } - - public static String discoverBeanDefinitionNameByQualifier(ListableBeanFactory beanFactory, String qualifier) { - Map beanMap = BeanFactoryAnnotationUtils.qualifiedBeansOfType(beanFactory, Object.class, qualifier); - if (!CollectionUtils.isEmpty(beanMap) && beanMap.size() == 1) { - return beanMap.keySet().iterator().next(); - } - return null; - } - - @SuppressWarnings("unchecked") - public static Type getOutputType(Type functionType) { - assertSupportedTypes(functionType); - if (isConsumer(functionType)) { - logger.debug("Consumer does not have output type, returning null as output type."); - return null; - } - Type outputType; - if (functionType instanceof Class) { - functionType = Function.class.isAssignableFrom((Class) functionType) - ? TypeResolver.reify(Function.class, (Class>) functionType) - : TypeResolver.reify(Supplier.class, (Class>) functionType); - } - - outputType = functionType instanceof ParameterizedType - ? (isSupplier(functionType) ? ((ParameterizedType) functionType).getActualTypeArguments()[0] : ((ParameterizedType) functionType).getActualTypeArguments()[1]) - : Object.class; - - return outputType; - } - - public static Type getImmediateGenericType(Type type, int index) { - if (type instanceof ParameterizedType) { - return ((ParameterizedType) type).getActualTypeArguments()[index]; - } - return null; - } - - public static boolean isPublisher(Type type) { - return isFlux(type) || isMono(type); - } - - public static boolean isFlux(Type type) { - return TypeResolver.resolveRawClass(type, null) == Flux.class; - } - - public static boolean isCollectionOfMessage(Type type) { - if (isMessage(type) && isTypeCollection(type)) { - return isMessage(getImmediateGenericType(type, 0)); - } - return false; - } - - public static boolean isMessage(Type type) { - if (isPublisher(type)) { - type = getImmediateGenericType(type, 0); - } - - Class resolveRawClass = FunctionTypeUtils.getRawType(type); - if (type instanceof ParameterizedType && !Message.class.isAssignableFrom(resolveRawClass)) { - type = getImmediateGenericType(type, 0); - } - resolveRawClass = FunctionTypeUtils.getRawType(type); - if (resolveRawClass == null) { - return false; - } - return Message.class.isAssignableFrom(resolveRawClass); - } - - /** - * Determines if input argument to a Function is an array. - * @param functionType the function type - * @return true if input type is an array, otherwise false - */ - public static boolean isOutputArray(Type functionType) { - Type outputType = FunctionTypeUtils.getOutputType(functionType); - return outputType instanceof GenericArrayType || outputType instanceof Class && ((Class) outputType).isArray(); - } - - public static boolean isSupplier(Type type) { - return isOfType(type, Supplier.class); - } - - public static boolean isFunction(Type type) { - return isOfType(type, Function.class); - } - - public static boolean isConsumer(Type type) { - return isOfType(type, Consumer.class); - } - - public static boolean isMono(Type type) { - type = extractReactiveType(type); - return type == null ? false : type.getTypeName().startsWith("reactor.core.publisher.Mono"); - } - - public static boolean isMultipleArgumentType(Type type) { - if (type != null) { - if (TypeResolver.resolveRawClass(type, null).isArray()) { - return false; - } - Class clazz = TypeResolver.resolveRawClass(TypeResolver.reify(type), null); - return clazz.getName().startsWith("reactor.util.function.Tuple"); - } - return false; - } - - static Type fromFunctionMethod(Method functionalMethod) { - Type[] parameterTypes = functionalMethod.getGenericParameterTypes(); - - Type functionType = null; - switch (parameterTypes.length) { - case 0: - functionType = ResolvableType.forClassWithGenerics(Supplier.class, - ResolvableType.forMethodReturnType(functionalMethod)).getType(); - break; - case 1: - if (Void.class.isAssignableFrom(functionalMethod.getReturnType())) { - functionType = ResolvableType.forClassWithGenerics(Consumer.class, - ResolvableType.forMethodParameter(functionalMethod, 0)).getType(); - } - else { - functionType = ResolvableType.forClassWithGenerics(Function.class, - ResolvableType.forMethodParameter(functionalMethod, 0), - ResolvableType.forMethodReturnType(functionalMethod)).getType(); - } - break; - default: - throw new UnsupportedOperationException("Functional method: " + functionalMethod + " is not supported"); - } - return functionType; - } - - private static boolean isMulti(Type type) { - return type.getTypeName().startsWith("reactor.util.function.Tuple"); - } - - private static boolean isOfType(Type type, Class cls) { - if (type instanceof Class) { - return cls.isAssignableFrom((Class) type); - } - else if (type instanceof ParameterizedType) { - return isOfType(((ParameterizedType) type).getRawType(), cls); - } - return false; - } - - private static void assertSupportedTypes(Type type) { - if (type instanceof ParameterizedType) { - type = ((ParameterizedType) type).getRawType(); - Assert.isTrue(type instanceof Class, "Must be one of Supplier, Function, Consumer" - + " or FunctionRegistration. Was " + type); - } - - Class candidateType = (Class) type; - - Assert.isTrue(Supplier.class.isAssignableFrom(candidateType) - || Function.class.isAssignableFrom(candidateType) - || Consumer.class.isAssignableFrom(candidateType) - || FunctionRegistration.class.isAssignableFrom(candidateType) - || type.getTypeName().startsWith("org.springframework.context.annotation.ConfigurationClassEnhancer"), "Must be one of Supplier, Function, Consumer" - + " or FunctionRegistration. Was " + type); - } - - private static Type extractReactiveType(Type type) { - if (type instanceof ParameterizedType && FunctionRegistration.class.isAssignableFrom(((Class) ((ParameterizedType) type).getRawType()))) { - type = getImmediateGenericType(type, 0); - if (type instanceof ParameterizedType) { - type = getImmediateGenericType(type, 0); - } - } - return type; - } - - private static String discoverDefinitionName(String functionDefinition, GenericApplicationContext applicationContext) { - String[] aliases = applicationContext.getAliases(functionDefinition); - for (String alias : aliases) { - if (applicationContext.getBeanFactory().containsBeanDefinition(alias)) { - return alias; - } - } - return functionDefinition; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionUnregistrationEvent.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionUnregistrationEvent.java deleted file mode 100644 index a8303e735..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionUnregistrationEvent.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.context.catalog; - -import java.util.HashSet; -import java.util.Set; - -/** - * @author Dave Syer - * - */ -@SuppressWarnings("serial") -public class FunctionUnregistrationEvent extends FunctionCatalogEvent { - - private final Class type; - - private final Set names; - - public FunctionUnregistrationEvent(Object source, Class type, Set names) { - super(source); - this.type = type; - this.names = new HashSet<>(names); - } - - public Class getType() { - return this.type; - } - - public Set getNames() { - return this.names; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/HeaderEnricher.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/HeaderEnricher.java deleted file mode 100644 index ff8e1ebe7..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/HeaderEnricher.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2021-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.context.catalog; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.context.expression.MapAccessor; -import org.springframework.expression.BeanResolver; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; - -/** - * Class responsible for processing `input-header-mapping-expression` - * and modifying message headers accordingly. - * - * @author Oleg Zhurakousky - * - * @since 3.1.3 - * - */ -class HeaderEnricher implements Function { - - protected Log logger = LogFactory.getLog(HeaderEnricher.class); - - private final Map> headerExpressions; - - private final SpelExpressionParser spelParser = new SpelExpressionParser(); - - private final StandardEvaluationContext evalContext = new StandardEvaluationContext(); - - @SuppressWarnings({ "rawtypes", "unchecked" }) - HeaderEnricher(Map headerExpressions, @Nullable BeanResolver beanResolver) { - Assert.notEmpty(headerExpressions, "'headerExpressions' must not be null or empty"); - this.headerExpressions = headerExpressions; - this.evalContext.addPropertyAccessor(new MapAccessor()); - if (beanResolver != null) { - this.evalContext.setBeanResolver(beanResolver); - } - } - - @Override - public Object apply(Object input) { - if (input instanceof Message) { - MessageBuilder messageBuilder = MessageBuilder.fromMessage((Message) input); - Map mappings = this.headerExpressions.get("0"); - for (Entry keyValueExpressionEntry : mappings.entrySet()) { - Expression expression = this.spelParser.parseExpression(keyValueExpressionEntry.getValue()); - try { - Object value = expression.getValue(this.evalContext, input, Object.class); - messageBuilder.setHeader(keyValueExpressionEntry.getKey(), value); - } - catch (Exception e) { - String message = "Failed while evaluating expression \"" + keyValueExpressionEntry.getValue() + "\" on incoming message"; - if (logger.isDebugEnabled()) { - logger.warn(message + ": " + input, e); - } - else { - logger.warn(message); - } - } - } - input = messageBuilder.build(); - } - - return input; - } - -} 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 deleted file mode 100644 index 08a91bce8..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java +++ /dev/null @@ -1,1537 +0,0 @@ -/* - * Copyright 2019-2023 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 java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -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 reactor.util.function.Tuples; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionProperties.FunctionConfigurationProperties; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.PostProcessingFunction; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.core.FunctionInvocationHelper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.core.ResolvableType; -import org.springframework.core.convert.ConversionService; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - - -/** - * Implementation of {@link FunctionCatalog} and {@link FunctionRegistry} which - * does not depend on Spring's {@link BeanFactory}. - * Each function must be registered with it explicitly to benefit from features - * such as type conversion, composition, POJO etc. - * - * @author Oleg Zhurakousky - * @author Roman Samarev - * @author Soby Chacko - * @author Chris Bono - */ -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? - * - */ - - private final Set> functionRegistrations = new CopyOnWriteArraySet<>(); - - private final Map wrappedFunctionDefinitions = new HashMap<>(); - - private final ConversionService conversionService; - - private final CompositeMessageConverter messageConverter; - - private final JsonMapper jsonMapper; - - private final FunctionInvocationHelper> functionInvocationHelper; - - private final FunctionProperties functionProperties; - - @Autowired(required = false) - private FunctionAroundWrapper functionAroundWrapper; - - public SimpleFunctionRegistry(ConversionService conversionService, CompositeMessageConverter messageConverter, JsonMapper jsonMapper, - @Nullable FunctionProperties functionProperties, - @Nullable FunctionInvocationHelper> functionInvocationHelper) { - Assert.notNull(messageConverter, "'messageConverter' must not be null"); - Assert.notNull(jsonMapper, "'jsonMapper' must not be null"); - this.conversionService = conversionService; - this.jsonMapper = jsonMapper; - this.messageConverter = messageConverter; - this.functionInvocationHelper = functionInvocationHelper; - this.functionProperties = functionProperties; - } - - /** - * Will add provided {@link MessageConverter}s to the head of the stack of the existing MessageConverters. - * - * @param messageConverters list of {@link MessageConverter}s. - */ - public void addMessageConverters(Collection messageConverters) { - if (!CollectionUtils.isEmpty(messageConverters)) { - this.messageConverter.getConverters().addAll(0, messageConverters); - } - } - - public SimpleFunctionRegistry(ConversionService conversionService, CompositeMessageConverter messageConverter, JsonMapper jsonMapper) { - this(conversionService, messageConverter, jsonMapper, null, null); - } - - @SuppressWarnings("unchecked") - @Override - public T lookup(Class type, String functionDefinition, String... expectedOutputMimeTypes) { - functionDefinition = this.normalizeFunctionDefinition(functionDefinition); - FunctionInvocationWrapper function = this.doLookup(type, functionDefinition, expectedOutputMimeTypes); - if (logger.isDebugEnabled()) { - if (function != null) { - logger.debug("Located function: " + function); - } - else { - logger.debug("Failed to locate function: " + functionDefinition); - } - } - return (T) function; - } - - @Override - public void register(FunctionRegistration registration) { - if (!isRegistrationEligible(registration)) { - return; - } - Assert.notNull(registration, "'registration' must not be null"); - if (logger.isDebugEnabled()) { - logger.debug("Registering function " + registration.getNames()); - } - this.functionRegistrations.add(registration); - } - - @SuppressWarnings("rawtypes") - private boolean isRegistrationEligible(FunctionRegistration registration) { - if (this.functionProperties != null) { - for (String definition : this.functionProperties.getIneligibleDefinitions()) { - if (registration.getTarget().getClass().getName().equals(definition)) { - return false; - } - else if (registration.getNames().contains(definition) || registration.getTarget().getClass().getName().contains(definition)) { - return false; - } - } - } - return true; - } - - boolean isFunctionDefinitionEligible(String functionDefinition) { - if (this.functionProperties != null) { - for (String definition : this.functionProperties.getIneligibleDefinitions()) { - if (functionDefinition.contains(definition)) { - return false; - } - } - } - return true; - } - - //----- - - @Override - public Set getNames(Class type) { - return this.functionRegistrations.stream().flatMap(fr -> fr.getNames().stream()).collect(Collectors.toSet()); - } - - @Override - public int size() { - return this.functionRegistrations.size(); - } - - /* - * - */ - protected boolean containsFunction(String functionName) { - return this.functionRegistrations.stream().anyMatch(reg -> reg.getNames().contains(functionName)); - } - - /* - * - */ - @SuppressWarnings("unchecked") - T doLookup(Class type, String functionDefinition, String[] expectedOutputMimeTypes) { - FunctionInvocationWrapper function = this.wrappedFunctionDefinitions.get(functionDefinition); - if (function == null) { - function = this.compose(type, functionDefinition); - } - - if (function != null) { - if (!ObjectUtils.isEmpty(expectedOutputMimeTypes)) { - function.expectedOutputContentType = expectedOutputMimeTypes; - } - } - else if (logger.isDebugEnabled()) { - logger.debug("Function '" + functionDefinition + "' is not found in cache"); - } - - return (T) function; - } - - /** - * This method will make sure that if there is only one function in catalog - * it can be looked up by any name or no name. - * It does so by attempting to determine the default function name - * (the only function in catalog) and checking if it matches the provided name - * replacing it if it does not. - */ - String normalizeFunctionDefinition(String functionDefinition) { - functionDefinition = StringUtils.hasText(functionDefinition) - ? functionDefinition.replaceAll(",", "|") - : System.getProperty(FunctionProperties.FUNCTION_DEFINITION, ""); - - Set names = this.getNames(null); - if (!names.contains(functionDefinition)) { - List eligibleFunction = names.stream() - .filter(name -> !RoutingFunction.FUNCTION_NAME.equals(name)) - .filter(name -> !RoutingFunction.DEFAULT_ROUTE_HANDLER.equals(name)) - .collect(Collectors.toList()); - if (eligibleFunction.size() == 1 - && !eligibleFunction.get(0).equals(functionDefinition) - && !functionDefinition.contains("|") - && !eligibleFunction.get(0).startsWith("&")) { - functionDefinition = eligibleFunction.get(0); - } - } - return functionDefinition; - } - - /* - * - */ - private FunctionInvocationWrapper findFunctionInFunctionRegistrations(String functionName) { - FunctionRegistration functionRegistration = this.functionRegistrations.stream() - .filter(fr -> fr.getNames().contains(functionName)) - .findFirst() - .orElseGet(() -> null); - FunctionInvocationWrapper function = functionRegistration != null - ? this.invocationWrapperInstance(functionName, functionRegistration.getTarget(), functionRegistration.getType()) - : null; - if (functionRegistration != null) { - Object userFunction = functionRegistration.getUserFunction(); - if (userFunction instanceof BiConsumer && function != null) { - function.setWrappedBiConsumer(true); - } - } - if (functionRegistration != null && functionRegistration.getProperties().containsKey("singleton")) { - try { - function.isSingleton = Boolean.parseBoolean(functionRegistration.getProperties().get("singleton")); - } - catch (Exception e) { - // ignore - } - } - return function; - } - - /* - * - */ - private FunctionInvocationWrapper compose(Class type, String functionDefinition) { - String[] functionNames = StringUtils.delimitedListToStringArray(functionDefinition.replaceAll(",", "|").trim(), "|"); - FunctionInvocationWrapper composedFunction = null; - - for (String functionName : functionNames) { - FunctionInvocationWrapper function = this.findFunctionInFunctionRegistrations(functionName); - if (function == null) { - return null; - } - else { - if (composedFunction == null) { - composedFunction = function; - } - else { - FunctionInvocationWrapper andThenFunction = - invocationWrapperInstance(functionName, function.getTarget(), function.inputType, function.outputType); - composedFunction = (FunctionInvocationWrapper) composedFunction.andThen((Function) andThenFunction); - } - composedFunction = this.enrichInputIfNecessary(composedFunction); - composedFunction = this.enrichOutputIfNecessary(composedFunction); - if (composedFunction.isSingleton) { - this.wrappedFunctionDefinitions.put(composedFunction.functionDefinition, composedFunction); - } - } - } - if (logger.isDebugEnabled()) { - logger.debug("Composed function " + composedFunction); - } - return composedFunction; - } - - private FunctionInvocationWrapper enrichInputIfNecessary(FunctionInvocationWrapper composedFunction) { - if (this.functionProperties == null) { - return composedFunction; - } - String functionDefinition = composedFunction.getFunctionDefinition(); - Map configurationProperties = this.functionProperties.getConfiguration(); - if (!CollectionUtils.isEmpty(configurationProperties)) { - FunctionConfigurationProperties configuration = configurationProperties - .get(functionDefinition.replace("|", "").replace(",", "")); - if (configuration != null) { - if (!CollectionUtils.isEmpty(configuration.getInputHeaderMappingExpression())) { - BeanFactoryResolver beanResolver = this.functionProperties.getApplicationContext() != null - ? new BeanFactoryResolver(this.functionProperties.getApplicationContext()) - : null; - HeaderEnricher enricher = new HeaderEnricher(configuration.getInputHeaderMappingExpression(), beanResolver); - FunctionInvocationWrapper w = new FunctionInvocationWrapper("inputHeaderEnricher", enricher, Message.class, Message.class); - composedFunction = (FunctionInvocationWrapper) w.andThen((Function) composedFunction); - composedFunction.functionDefinition = functionDefinition; - } - } - } - return composedFunction; - } - - private FunctionInvocationWrapper enrichOutputIfNecessary(FunctionInvocationWrapper composedFunction) { - if (this.functionProperties == null) { - return composedFunction; - } - String functionDefinition = composedFunction.getFunctionDefinition(); - Map configurationProperties = this.functionProperties.getConfiguration(); - if (!CollectionUtils.isEmpty(configurationProperties)) { - FunctionConfigurationProperties configuration = configurationProperties - .get(functionDefinition.replace("|", "").replace(",", "")); - if (configuration != null) { - if (!CollectionUtils.isEmpty(configuration.getOutputHeaderMappingExpression())) { - BeanFactoryResolver beanResolver = this.functionProperties.getApplicationContext() != null - ? new BeanFactoryResolver(this.functionProperties.getApplicationContext()) - : null; - HeaderEnricher enricher = new HeaderEnricher(configuration.getOutputHeaderMappingExpression(), beanResolver); - Type mesageType = ResolvableType.forClassWithGenerics(Message.class, Object.class).getType(); - FunctionInvocationWrapper enricherWrapper = new FunctionInvocationWrapper("outputHeaderEnricher", enricher, mesageType, mesageType); - composedFunction = (FunctionInvocationWrapper) composedFunction.andThen((Function) enricherWrapper); - composedFunction.functionDefinition = functionDefinition; - } - } - } - return composedFunction; - } - - /* - * - */ - private FunctionInvocationWrapper invocationWrapperInstance(String functionDefinition, Object target, Type inputType, Type outputType) { - return new FunctionInvocationWrapper(functionDefinition, target, inputType, outputType); - } - - /* - * - */ - private FunctionInvocationWrapper invocationWrapperInstance(String functionDefinition, Object target, Type functionType) { - return invocationWrapperInstance(functionDefinition, target, - FunctionTypeUtils.isSupplier(functionType) ? null : FunctionTypeUtils.getInputType(functionType), - FunctionTypeUtils.getOutputType(functionType)); - } - - /** - * - */ - @SuppressWarnings("rawtypes") - public class FunctionInvocationWrapper implements Function, Consumer, Supplier, Runnable { - - private final Object target; - - private Type inputType; - - private final Type outputType; - - private String functionDefinition; - - private boolean composed; - - private boolean message; - - private String[] expectedOutputContentType; - - private boolean skipInputConversion; - - private boolean skipOutputConversion; - - private boolean isSingleton = true; - - private boolean propagateInputHeaders; - - private boolean wrapped; - - private final ThreadLocal> unconvertedResult = new ThreadLocal<>(); - - private PostProcessingFunction postProcessor; - - /* - * This is primarily to support Stream's ability to access - * un-converted payload (e.g., to evaluate expression on some attribute of a payload) - * It is not intended to remain here and will be removed as soon as particular elements - * of stream will be refactored to address this. - */ - private Function enhancer; - - private boolean wrappedBiConsumer; - - FunctionInvocationWrapper(String functionDefinition, Object target, Type inputType, Type outputType) { - if (target instanceof PostProcessingFunction) { - this.postProcessor = (PostProcessingFunction) target; - } - this.target = target; - this.inputType = this.normalizeType(inputType); - this.outputType = this.normalizeType(outputType); - this.functionDefinition = functionDefinition; - this.message = this.inputType != null && FunctionTypeUtils.isMessage(this.inputType); - if (functionProperties != null) { - Map funcConfiguration = functionProperties.getConfiguration(); - if (!CollectionUtils.isEmpty(funcConfiguration)) { - FunctionConfigurationProperties configuration = funcConfiguration.get(functionDefinition); - if (configuration != null) { - propagateInputHeaders = configuration.isCopyInputHeaders(); - } - } - } - } - - @SuppressWarnings("unchecked") - public void postProcess() { - if (this.postProcessor != null) { - Message result = this.unconvertedResult.get(); - if (result != null) { - try { - this.postProcessor.postProcess(result); - } - catch (Exception ex) { - logger.warn("Failed to post process function " - + this.functionDefinition + "; Result of the invocation before post processing is " + result, ex); - } - finally { - this.unconvertedResult.remove(); - } - } - } - } - - public boolean isWrappedBiConsumer() { - return wrappedBiConsumer; - } - - public void setWrappedBiConsumer(boolean wrappedBiConsumer) { - this.wrappedBiConsumer = wrappedBiConsumer; - } - - public boolean isSkipOutputConversion() { - return skipOutputConversion; - } - - - public boolean isPrototype() { - return !this.isSingleton; - } - - public void setSkipInputConversion(boolean skipInputConversion) { - if (logger.isDebugEnabled() && skipInputConversion) { - logger.debug("'skipInputConversion' was explicitely set to true. No input conversion will be attempted"); - } - this.skipInputConversion = skipInputConversion; - } - - public void setSkipOutputConversion(boolean skipOutputConversion) { - if (logger.isDebugEnabled() && skipOutputConversion) { - logger.debug("'skipOutputConversion' was explicitely set to true. No output conversion will be attempted"); - } - this.skipOutputConversion = skipOutputConversion; - } - - /** - * !!! INTERNAL USE ONLY !!! - * This is primarily to support s-c-Stream's ability to access - * un-converted payload (e.g., to evaluate expression on some attribute of a payload) - * It is not intended to remain here and will be removed as soon as particular elements - * of stream will be refactored to address this. - */ - public Function getEnhancer() { - return this.enhancer; - } - - public Type getOutputType() { - return this.outputType; - } - - /** - * !!! INTERNAL USE ONLY !!! - * This is primarily to support s-c-Stream's ability to access - * un-converted payload (e.g., to evaluate expression on some attribute of a payload) - * It is not intended to remain here and will be removed as soon as particular elements - * of stream will be refactored to address this. - */ - public void setEnhancer(Function enhancer) { - this.enhancer = enhancer; - } - - public Object getTarget() { - return target; - } - - public Type getInputType() { - return this.inputType; - } - - /** - * Return the actual {@link Type} of the item of the provided type. - * This method is context specific and is not a general purpose utility method. The context is that the provided - * {@link Type} may represent the input/output of a function where such type could be wrapped in - * {@link Message}, {@link Flux} or {@link Mono}, so this method returns generic value of such type or itself if not wrapped. - * @param type typically input or output Type of the function (see {@link #getInputType()} or {@link #getOutputType()}. - * @return the type of the item if wrapped otherwise the provided type. - */ - public Type getItemType(Type type) { - if (FunctionTypeUtils.isPublisher(type) || FunctionTypeUtils.isMessage(type) || FunctionTypeUtils.isTypeCollection(type)) { - type = FunctionTypeUtils.getGenericType(type); - } - if (FunctionTypeUtils.isMessage(type)) { - type = FunctionTypeUtils.getGenericType(type); - } - return type; - } - - public Class getRawOutputType() { - return this.outputType == null ? null : FunctionTypeUtils.getRawType(this.outputType); - } - - public Class getRawInputType() { - return this.inputType == null ? null : FunctionTypeUtils.getRawType(this.inputType); - } - - /** - * - */ - @Override - public Object apply(Object input) { - if (logger.isDebugEnabled() && !(input instanceof Publisher)) { - logger.debug("Invoking function " + this); - } - - Object result; - if (functionAroundWrapper != null && !this.wrapped) { - this.wrapped = true; - result = functionAroundWrapper.apply(input, this); - } - else { - result = this.doApply(input); - } - - return result; - } - - @Override - public Object get() { - return this.apply(null); - } - - @Override - public void accept(Object input) { - this.apply(input); - } - - @Override - public void run() { - this.apply(null); - } - - public boolean isConsumer() { - return this.outputType == null; - } - - public boolean isSupplier() { - return this.inputType == null; - } - - public boolean isFunction() { - return this.inputType != null && this.outputType != null; - } - - public boolean isInputTypePublisher() { - return this.isTypePublisher(this.inputType); - } - - public boolean isOutputTypePublisher() { - return this.isTypePublisher(this.outputType); - } - - public boolean isInputTypeMessage() { - boolean b = this.message || this.isRoutingFunction(); - return b; - } - - public boolean isOutputTypeMessage() { - return FunctionTypeUtils.isMessage(this.outputType); - } - - - public boolean isRoutingFunction() { - return this.target instanceof RoutingFunction; - } - - /* - * - */ - @SuppressWarnings("unchecked") - @Override - public Function andThen(Function after) { - Assert.isTrue(after instanceof FunctionInvocationWrapper, "Composed function must be an instanceof FunctionInvocationWrapper."); - if (FunctionTypeUtils.isMultipleArgumentType(this.inputType) - || FunctionTypeUtils.isMultipleArgumentType(this.outputType) - || FunctionTypeUtils.isMultipleArgumentType(((FunctionInvocationWrapper) after).inputType) - || FunctionTypeUtils.isMultipleArgumentType(((FunctionInvocationWrapper) after).outputType)) { - throw new UnsupportedOperationException("Composition of functions with multiple arguments is not supported at the moment"); - } - - Function rawComposedFunction = v -> ((FunctionInvocationWrapper) after).doApply(doApply(v)); - - FunctionInvocationWrapper afterWrapper = (FunctionInvocationWrapper) after; - - Type composedFunctionType; - if (afterWrapper.outputType == null) { - composedFunctionType = (this.inputType == null) ? - ResolvableType.forClassWithGenerics(Supplier.class, ResolvableType.forType(Object.class)).getType() : - ResolvableType.forClassWithGenerics(Consumer.class, ResolvableType.forType(this.inputType)).getType(); - } - else if (this.inputType == null && afterWrapper.outputType != null) { - ResolvableType composedOutputType; - if (FunctionTypeUtils.isFlux(this.outputType)) { - composedOutputType = ResolvableType.forClassWithGenerics(Flux.class, ResolvableType.forType(afterWrapper.outputType)); - } - else if (FunctionTypeUtils.isMono(this.outputType)) { - composedOutputType = ResolvableType.forClassWithGenerics(Mono.class, ResolvableType.forType(afterWrapper.outputType)); - } - else { - composedOutputType = ResolvableType.forType(afterWrapper.outputType); - } - - composedFunctionType = ResolvableType.forClassWithGenerics(Supplier.class, composedOutputType).getType(); - } - else if (this.outputType == null) { - throw new IllegalArgumentException("Can NOT compose anything with Consumer"); - } - else { - composedFunctionType = ResolvableType.forClassWithGenerics(Function.class, - ResolvableType.forType(this.inputType), - ResolvableType.forType(((FunctionInvocationWrapper) after).outputType)).getType(); - } - - String composedName = this.functionDefinition + "|" + afterWrapper.functionDefinition; - FunctionInvocationWrapper composedFunction = invocationWrapperInstance(composedName, rawComposedFunction, composedFunctionType); - composedFunction.composed = true; - if (((FunctionInvocationWrapper) after).target instanceof PostProcessingFunction) { - composedFunction.postProcessor = (PostProcessingFunction) ((FunctionInvocationWrapper) after).target; - } - - return (Function) composedFunction; - } - - /** - * Returns the definition of this function. - * @return function definition - */ - public String getFunctionDefinition() { - return this.functionDefinition; - } - - /* - * - */ - @Override - public String toString() { - return this.functionDefinition + (this.isComposed() ? "" : "<" + this.inputType + ", " + this.outputType + ">"); - } - - /** - * Returns true if this function wrapper represents a composed function. - * @return true if this function wrapper represents a composed function otherwise false - */ - boolean isComposed() { - return this.composed; - } - - /* - * - */ - @SuppressWarnings("unchecked") - Object doApply(Object input) { - Object result; - - input = this.fluxifyInputIfNecessary(input); - - Object convertedInput = this.convertInputIfNecessary(input, this.inputType); - - if (this.isRoutingFunction() || this.isComposed()) { - result = ((Function) this.target).apply(convertedInput); - } - else if (this.isSupplier()) { - result = ((Supplier) this.target).get(); - } - else if (this.isConsumer()) { - result = this.invokeConsumer(convertedInput); - } - else { // Function - result = this.invokeFunction(convertedInput); - } - - if (this.postProcessor != null) { - this.unconvertedResult.set((Message) result); - } - - if (result != null && this.outputType != null) { - result = this.convertOutputIfNecessary(result, this.outputType, this.expectedOutputContentType); - } - return result; - } - - /* - * - */ - private boolean isTypePublisher(Type type) { - return type != null && FunctionTypeUtils.isPublisher(type); - } - - /** - * Will return Object.class if type is represented as TypeVariable(T) or WildcardType(?). - */ - private Type normalizeType(Type type) { - if (type != null) { - return !(type instanceof TypeVariable) && !(type instanceof WildcardType) ? type : Object.class; - } - return type; - } - - /* - * - */ - private Class getRawClassFor(@Nullable Type type) { - return type instanceof TypeVariable || type instanceof WildcardType - ? Object.class - : FunctionTypeUtils.getRawType(type); - } - - /** - * Will wrap the result in a Message if necessary and will copy input headers to the output message. - */ - private Object enrichInvocationResultIfNecessary(Object input, Object result) { - if (result != null && !(result instanceof Publisher) && input instanceof Message) { - if (result instanceof Message) { - if (functionInvocationHelper != null && CloudEventMessageUtils.isCloudEvent(((Message) input))) { - result = functionInvocationHelper.postProcessResult(result, (Message) input); - } - } - else { - if (functionInvocationHelper != null && CloudEventMessageUtils.isCloudEvent(((Message) input))) { - result = functionInvocationHelper.postProcessResult(result, (Message) input); - } - else if (!FunctionTypeUtils.isCollectionOfMessage(this.outputType)) { - result = MessageBuilder.withPayload(result).copyHeaders(this.sanitizeHeaders(((Message) input).getHeaders())).build(); - } - } - } - return result; - } - - /* - * Will ensure no headers with null values are copied. - */ - private Map sanitizeHeaders(MessageHeaders headers) { - Map sanitizedHeaders = new HashMap<>(); - headers.forEach((k, v) -> { - if (v != null) { - sanitizedHeaders.put(k, v); - } - }); - return sanitizedHeaders; - } - - @SuppressWarnings("unchecked") - private Object fluxifyInputIfNecessary(Object input) { - if (input instanceof Message && !((Message) input).getHeaders().containsKey("user-agent") && this.isConsumer() && !this.isInputTypePublisher()) { - return input; - } - if (FunctionTypeUtils.isMultipleArgumentType(this.inputType)) { - return input; - } - - if (!this.isRoutingFunction() && !(input instanceof Publisher)) { - Object payload = input; - var treatPayloadAsPlainText = false; - if (input instanceof Message msg) { - if (msg.getHeaders().containsKey("payload")) { - payload = msg.getHeaders().get("payload"); - } - else { - payload = msg.getPayload(); - } - treatPayloadAsPlainText = contentTypeHeaderValue(msg).equals(MimeTypeUtils.TEXT_PLAIN_VALUE); - } - - if ((!treatPayloadAsPlainText && JsonMapper.isJsonStringRepresentsCollection(payload)) - && !FunctionTypeUtils.isTypeCollection(this.inputType) - && !FunctionTypeUtils.isTypeArray(this.inputType)) { - MessageHeaders headers = ((Message) input).getHeaders(); - Collection collectionPayload = jsonMapper.fromJson(payload, Collection.class); - Class inputClass = FunctionTypeUtils.getRawType(this.inputType); - if (this.isInputTypeMessage()) { - inputClass = FunctionTypeUtils.getRawType(FunctionTypeUtils.getImmediateGenericType(this.inputType, 0)); - } - - if (!inputClass.isAssignableFrom(Object.class) && !inputClass.isAssignableFrom(byte[].class)) { - logger.debug("Converting JSON string representing collection to a list of Messages. Function '" - + this + "' will be invoked iteratively"); - input = collectionPayload.stream() - .map(p -> MessageBuilder.withPayload(p).copyHeaders(headers).build()) - .collect(Collectors.toList()); - } - } - } - - if (this.isTypePublisher(this.inputType) && !(input instanceof Publisher)) { - if (input == null) { - input = FunctionTypeUtils.isMono(this.inputType) ? Mono.empty() : Flux.empty(); - } - else if (input instanceof Message && ((Message) input).getPayload() instanceof Iterable) { - input = FunctionTypeUtils.isMono(this.inputType) ? Mono.just(input) : Flux.just(input).flatMap(v -> { - if (logger.isDebugEnabled()) { - logger.debug("Creating Flux from Iterable: " + ((Message) v).getPayload()); - } - return Flux.fromIterable((Iterable) ((Message) v).getPayload()); - }); - } - else if (input instanceof Iterable) { - input = FunctionTypeUtils.isMono(this.inputType) ? Mono.just(input) : Flux.fromIterable((Iterable) input); - - } - else { - input = FunctionTypeUtils.isMono(this.inputType) ? Mono.just(input) : Flux.just(input); - } - } - else if (!(input instanceof Publisher) && input instanceof Iterable && !FunctionTypeUtils.isTypeCollection(this.inputType)) { - input = Flux.fromIterable((Iterable) input); - } - return input; - } - - private String contentTypeHeaderValue(Message msg) { - var contentType = msg.getHeaders().get(MessageHeaders.CONTENT_TYPE); - if (contentType == null) { - contentType = msg.getHeaders().get(HttpHeaders.CONTENT_TYPE); - if (contentType == null) { - contentType = msg.getHeaders().get(HttpHeaders.CONTENT_TYPE.toLowerCase()); - } - } - return Objects.toString(contentType); - } - - @SuppressWarnings("unchecked") - private Object invokeFunction(Object convertedInput) { - Object result; - if (!this.isTypePublisher(this.inputType) && convertedInput instanceof Publisher) { - result = convertedInput instanceof Mono - ? Mono.from((Publisher) convertedInput).map(value -> this.invokeFunctionAndEnrichResultIfNecessary(value)) - .doOnError(ex -> logger.error("Failed to invoke function '" + this.functionDefinition + "'", (Throwable) ex)) - : Flux.from((Publisher) convertedInput).map(value -> this.invokeFunctionAndEnrichResultIfNecessary(value)) - .doOnError(ex -> logger.error("Failed to invoke function '" + this.functionDefinition + "'", (Throwable) ex)); - } - else { - result = this.invokeFunctionAndEnrichResultIfNecessary(convertedInput); - if (result instanceof Flux) { - result = ((Flux) result).doOnError(ex -> logger.error("Failed to invoke function '" - + this.functionDefinition + "'", (Throwable) ex)); - } - else if (result instanceof Mono) { - result = ((Mono) result).doOnError(ex -> logger.error("Failed to invoke function '" - + this.functionDefinition + "'", (Throwable) ex)); - } - } - return result; - } - - /* - * - */ - @SuppressWarnings("unchecked") - private Object invokeFunctionAndEnrichResultIfNecessary(Object value) { - AtomicReference> firstInputMessage = new AtomicReference<>(); - - Object inputValue; - if (value instanceof Flux) { - inputValue = ((Flux) value).map(v -> { - if (v instanceof OriginalMessageHolder && firstInputMessage.get() == null) { - firstInputMessage.set(((OriginalMessageHolder) v).getOriginalMessage()); - } - return this.extractValueFromOriginalValueHolderIfNecessary(v); - }); - } - else if (value instanceof Mono) { - inputValue = ((Mono) value).map(v -> { - if (v instanceof OriginalMessageHolder) { - firstInputMessage.set(((OriginalMessageHolder) v).getOriginalMessage()); - } - return this.extractValueFromOriginalValueHolderIfNecessary(v); - }); - } - else { - inputValue = this.extractValueFromOriginalValueHolderIfNecessary(value); - } - - if (!(this.target instanceof PassThruFunction) && inputValue instanceof Message && !this.isInputTypeMessage()) { - inputValue = ((Message) inputValue).getPayload(); - } - - if (logger.isDebugEnabled()) { - logger.debug("Invoking function: " + this + "with input type: " + this.getInputType()); - } - - Object result; - if (inputValue != null && inputValue.getClass().getName().equals("org.springframework.kafka.support.KafkaNull")) { - result = ((Function) this.target).apply(null); - } - else { - result = ((Function) this.target).apply(inputValue); - } - - if (result instanceof Publisher && functionInvocationHelper != null) { - result = this.postProcessFunction((Publisher) result, firstInputMessage); - } - - return value instanceof OriginalMessageHolder - ? this.enrichInvocationResultIfNecessary(((OriginalMessageHolder) value).getOriginalMessage(), result) - : result; - } - - @SuppressWarnings("unchecked") - private Publisher postProcessFunction(Publisher result, AtomicReference> firstInputMessage) { - if (FunctionTypeUtils.isPublisher(this.inputType) && FunctionTypeUtils.isPublisher(this.outputType)) { - if (!FunctionTypeUtils.getRawType(FunctionTypeUtils.getImmediateGenericType(this.inputType, 0)) - .isAssignableFrom(Void.class) - && !FunctionTypeUtils.getRawType(FunctionTypeUtils.getImmediateGenericType(this.outputType, 0)) - .isAssignableFrom(Void.class)) { - - if (result instanceof Mono) { - return Mono.from((result)).map(v -> { - if (firstInputMessage.get() != null && CloudEventMessageUtils - .isCloudEvent(firstInputMessage.get())) { - return functionInvocationHelper.postProcessResult(v, - firstInputMessage.get()); - } - return v; - }); - } - else { - return Flux.from((result)).map(v -> { - if (firstInputMessage.get() != null && CloudEventMessageUtils - .isCloudEvent(firstInputMessage.get())) { - return functionInvocationHelper.postProcessResult(v, - firstInputMessage.get()); - } - return v; - }); - } - } - } - - return result; - } - - /* - * - */ - @SuppressWarnings("unchecked") - private Object invokeConsumer(Object convertedInput) { - Object result = null; - if (this.isTypePublisher(this.inputType)) { - if (convertedInput instanceof Flux) { - result = ((Flux) convertedInput) - .transform(flux -> { - flux = Flux.from((Publisher) flux).map(v -> this.extractValueFromOriginalValueHolderIfNecessary(v)); - ((Consumer) this.target).accept(flux); - return Mono.ignoreElements((Flux) flux); - }).then(); - } - else { - result = ((Mono) convertedInput) - .transform(mono -> { - mono = Mono.from((Publisher) mono).map(v -> this.extractValueFromOriginalValueHolderIfNecessary(v)); - ((Consumer) this.target).accept(mono); - return Mono.ignoreElements((Mono) mono); - }).then(); - } - } - else if (convertedInput instanceof Publisher) { - result = convertedInput instanceof Mono - ? Mono.from((Publisher) convertedInput) - .map(v -> this.extractValueFromOriginalValueHolderIfNecessary(v)) - .doOnNext((Consumer) this.target).then() - : Flux.from((Publisher) convertedInput) - .map(v -> this.extractValueFromOriginalValueHolderIfNecessary(v)) - .doOnNext((Consumer) this.target).then(); - } - else { - Object extractedValue = this.extractValueFromOriginalValueHolderIfNecessary(convertedInput); - ((Consumer) this.target).accept(extractedValue); - } - return result; - } - - private Object extractValueFromOriginalValueHolderIfNecessary(Object input) { - if (input instanceof OriginalMessageHolder) { - input = ((OriginalMessageHolder) input).getValue(); - } - return input; - } - - /** - * This operation will parse value coming in as Tuples to Object[]. - */ - private Object[] parseMultipleValueArguments(Object multipleValueArgument, int argumentCount) { - Object[] parsedArgumentValues = new Object[argumentCount]; - if (multipleValueArgument.getClass().getName().startsWith("reactor.util.function.Tuple")) { - for (int i = 0; i < argumentCount; i++) { - Expression parsed = new SpelExpressionParser().parseExpression("getT" + (i + 1) + "()"); - Object outputArgument = parsed.getValue(multipleValueArgument); - parsedArgumentValues[i] = outputArgument; - } - return parsedArgumentValues; - } - throw new UnsupportedOperationException("At the moment only Tuple-based function are supporting multiple arguments"); - } - - @SuppressWarnings("unchecked") - private boolean isInputConversionNecessary(Object input, Type type) { - if (type == null || this.getRawClassFor(type) == Void.class || this.target instanceof RoutingFunction || this.isComposed() || this.target instanceof PassThruFunction) { - if (this.getRawClassFor(type) == Void.class) { - if (input instanceof Message) { - input = ((Message) input).getPayload(); - if (input instanceof Optional) { - input = ((Optional) input).orElseGet(() -> null); - } - } - Assert.isNull(input, "Can't have non-null input with Void input type."); - } - return false; - } - return true; - } - /* - * - */ - private Object convertInputIfNecessary(Object input, Type type) { - if (!this.isInputConversionNecessary(input, type)) { - return input; - } - - Object convertedInput = null; - if (input instanceof Publisher) { - convertedInput = this.convertInputPublisherIfNecessary((Publisher) input, type); - } - else if (FunctionTypeUtils.isMultipleArgumentType(type)) { - Type[] inputTypes = ((ParameterizedType) type).getActualTypeArguments(); - Object[] multipleValueArguments = this.parseMultipleValueArguments(input, inputTypes.length); - Object[] convertedInputs = new Object[inputTypes.length]; - for (int i = 0; i < multipleValueArguments.length; i++) { - Object cInput = this.convertInputIfNecessary(multipleValueArguments[i], inputTypes[i]); - convertedInputs[i] = cInput; - } - convertedInput = Tuples.fromArray(convertedInputs); - } - else if (this.skipInputConversion) { - convertedInput = this.isInputTypeMessage() - ? input - : new OriginalMessageHolder(((Message) input).getPayload(), (Message) input); - } - else if (input instanceof Message) { - input = this.filterOutHeaders((Message) input); - if (((Message) input).getPayload().getClass().getName().equals("org.springframework.kafka.support.KafkaNull")) { - return input; - } - - if (functionInvocationHelper != null) { - input = functionInvocationHelper.preProcessInput((Message) input, messageConverter); - } - - convertedInput = this.convertInputMessageIfNecessary((Message) input, type); - if (convertedInput == null) { // give ConversionService a chance - convertedInput = this.convertNonMessageInputIfNecessary(type, ((Message) input).getPayload(), false); - } - if (convertedInput != null && !FunctionTypeUtils.isMultipleArgumentType(this.inputType)) { - convertedInput = !convertedInput.equals(input) - ? new OriginalMessageHolder(convertedInput, (Message) input) - : convertedInput; - } - if (convertedInput != null && logger.isDebugEnabled()) { - logger.debug("Converted Message: " + input + " to: " + - (convertedInput instanceof OriginalMessageHolder ? ((OriginalMessageHolder) convertedInput).value.getClass() : convertedInput)); - } - } - else { - convertedInput = this.convertNonMessageInputIfNecessary(type, input, JsonMapper.isJsonString(input)); - if (convertedInput != null && logger.isDebugEnabled()) { - logger.debug("Converted input: " + input + " to: " + convertedInput); - } - } - // wrap in Message if necessary - if (this.isWrapConvertedInputInMessage(convertedInput)) { - convertedInput = MessageBuilder.withPayload(convertedInput).build(); - } - - Object finalInput = input; - Assert.notNull(convertedInput, () -> "Failed to convert input: " + finalInput + " to " + type); - return convertedInput; - } - - // TODO temporary fix for https://github.com/spring-cloud/spring-cloud-stream/issues/2178 - // need a cleaner solution - @SuppressWarnings("unchecked") - private Message filterOutHeaders(Message message) { - return MessageBuilder.fromMessage(message).removeHeader("spring.cloud.stream.sendto.destination").build(); - } - - private boolean isExtractPayload(Message message, Type type) { - if (this.propagateInputHeaders) { - return false; - } - if (this.isRoutingFunction()) { - return false; - } - if (FunctionTypeUtils.isCollectionOfMessage(type)) { - return true; - } - if (FunctionTypeUtils.isMessage(type)) { - return false; - } - - Object payload = message.getPayload(); - if ((payload instanceof byte[])) { - return false; - } - if (ObjectUtils.isArray(payload)) { - payload = CollectionUtils.arrayToList(payload); - } - if (payload instanceof Collection && !CollectionUtils.isEmpty((Collection) payload) - && Message.class.isAssignableFrom(CollectionUtils.findCommonElementType((Collection) payload))) { - return true; - } - if (this.containsRetainMessageSignalInHeaders(message)) { - return false; - } - return true; - } - - /** - * This is an optional conversion which would only happen if `expected-content-type` is - * set as a header in a message or explicitly provided as part of the lookup. - */ - @SuppressWarnings("unchecked") - private Object convertOutputIfNecessary(Object output, Type type, String[] contentType) { - Object convertedOutput = output; - if (this.skipOutputConversion) { - return convertedOutput; - } - - if (convertedOutput instanceof Publisher) { - return this.convertOutputPublisherIfNecessary((Publisher) convertedOutput, type, contentType); - } - - if (convertedOutput instanceof Message) { - if (((Message) convertedOutput).getPayload() instanceof byte[] && ObjectUtils.isEmpty(contentType)) { - return convertedOutput; - } - else if (isExtractPayload((Message) convertedOutput, type)) { - convertedOutput = ((Message) convertedOutput).getPayload(); - } - } - - if (this.enhancer != null) { - convertedOutput = enhancer.apply(convertedOutput); - } - if (this.getTarget() instanceof PassThruFunction) { // scst-2303 - Message enrichedMessage; - if (convertedOutput instanceof Message) { - enrichedMessage = MessageBuilder.fromMessage((Message) convertedOutput) - .setHeader(MessageHeaders.CONTENT_TYPE, contentType[0]).build(); - } - else { - enrichedMessage = MessageBuilder.withPayload(convertedOutput) - .setHeader(MessageHeaders.CONTENT_TYPE, contentType[0]).build(); - } - return messageConverter.toMessage(enrichedMessage.getPayload(), enrichedMessage.getHeaders()); - } - - if (ObjectUtils.isEmpty(contentType)) { - return convertedOutput; - } - - - if (FunctionTypeUtils.isMultipleArgumentType(type)) { - convertedOutput = this.convertMultipleOutputArgumentTypeIfNecesary(convertedOutput, type, contentType); - } - else if (convertedOutput instanceof Message) { - convertedOutput = this.convertOutputMessageIfNecessary(convertedOutput, ObjectUtils.isEmpty(contentType) ? null : contentType[0]); - } - else if (convertedOutput instanceof Collection && this.isOutputTypeMessage()) { - convertedOutput = this.convertMultipleOutputValuesIfNecessary(convertedOutput, ObjectUtils.isEmpty(contentType) ? null : contentType); - } - else if (ObjectUtils.isArray(convertedOutput) && !(convertedOutput instanceof byte[])) { - convertedOutput = this.convertMultipleOutputValuesIfNecessary(convertedOutput, ObjectUtils.isEmpty(contentType) ? null : contentType); - } - else { - convertedOutput = messageConverter.toMessage(convertedOutput, - new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, contentType == null ? "application/json" : contentType[0]))); - } - - return convertedOutput; - } - - /** - * Will check if message contains any of the headers that are considered to serve as - * signals to retain output as Message (regardless of the output type of function). - * At this moment presence of 'scf-func-name' header or any header that begins with `lambda' - * (use by AWS) will result in this method returning true. - */ - /* - * TODO we need to investigate if this could be extracted into some type of strategy since at - * the pure core level there is no case for this to ever be true. In fact today it is only AWS Lambda - * case that requires it since it may contain forwarding url - */ - private boolean containsRetainMessageSignalInHeaders(Message message) { - if (functionInvocationHelper != null && functionInvocationHelper.isRetainOuputAsMessage(message)) { - return true; - } - else { - for (String headerName : message.getHeaders().keySet()) { - if (headerName.startsWith("lambda") || - headerName.startsWith("scf-func-name")) { - return true; - } - } - return false; - } - } - - /* - * - */ - private Object convertNonMessageInputIfNecessary(Type inputType, Object input, boolean maybeJson) { - Object convertedInput = null; - Class rawInputType = this.isTypePublisher(inputType) || this.isInputTypeMessage() - ? FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType)) - : this.getRawClassFor(inputType); - - if (maybeJson && !Message.class.isAssignableFrom(rawInputType)) { - if (FunctionTypeUtils.isMessage(inputType)) { - inputType = FunctionTypeUtils.getGenericType(inputType); - } - if (Object.class != inputType) { - convertedInput = SimpleFunctionRegistry.this.jsonMapper.fromJson(input, inputType); - } - } - else if (SimpleFunctionRegistry.this.conversionService != null - && !rawInputType.equals(input.getClass()) - && SimpleFunctionRegistry.this.conversionService.canConvert(input.getClass(), rawInputType)) { - convertedInput = SimpleFunctionRegistry.this.conversionService.convert(input, rawInputType); - } - if (convertedInput == null && logger.isDebugEnabled()) { - logger.debug("Failed to convert input '" + input + "' to type " + inputType + ". Will use it as is."); - } - return convertedInput == null ? input : convertedInput; - } - - /* - * - */ - private boolean isWrapConvertedInputInMessage(Object convertedInput) { - return this.inputType != null - && FunctionTypeUtils.isMessage(this.inputType) - && !(convertedInput instanceof Message) - && !(convertedInput instanceof Publisher) - && !(convertedInput instanceof OriginalMessageHolder); - } - - /* - * - */ - private Type extractActualValueTypeIfNecessary(Type type) { - if (type instanceof ParameterizedType && (FunctionTypeUtils.isPublisher(type) || FunctionTypeUtils.isMessage(type))) { - return FunctionTypeUtils.getGenericType(type); - } - return type; - } - - /* - * - */ - private boolean isConversionHintRequired(Type actualType, Class rawType) { - if (Collection.class.isAssignableFrom(rawType) || Map.class.isAssignableFrom(rawType)) { - return true; - } - return rawType != actualType && !FunctionTypeUtils.isMessage(actualType); - } - - /* - * - */ - private Object convertInputMessageIfNecessary(Message message, Type type) { - if (type == null) { - return null; - } - if (message.getPayload() instanceof Optional) { - return message; - } - if (message.getPayload() instanceof Collection) { - Type itemType = FunctionTypeUtils.getImmediateGenericType(type, 0); - if (itemType == null) { - itemType = type; - } - Type collectionType = CollectionUtils.findCommonElementType((Collection) message.getPayload()); - if (collectionType == itemType) { - return message.getPayload(); - } - } - - Object convertedInput = message.getPayload(); - - Type itemType = this.extractActualValueTypeIfNecessary(type); - Class rawType = FunctionTypeUtils.isMessage(type) - ? FunctionTypeUtils.getRawType(itemType) - : FunctionTypeUtils.getRawType(type); - convertedInput = this.isConversionHintRequired(type, rawType) - ? SimpleFunctionRegistry.this.messageConverter.fromMessage(message, rawType, itemType) - : SimpleFunctionRegistry.this.messageConverter.fromMessage(message, rawType); - - if (convertedInput != null && !rawType.isAssignableFrom(convertedInput.getClass())) { - logger.warn("Failed to convert input to " + rawType + ". Will attempt to invoke function with raw type"); - } - - if (FunctionTypeUtils.isMessage(type)) { - if (convertedInput == null) { - if (logger.isDebugEnabled()) { - /* - * In the event conversion was unsuccessful we simply return the original un-converted message. - * This will help to deal with issues like KafkaNull and others. However if this was not the intention - * of the developer, this would be discovered early in the development process where the - * additional message converter could be added to facilitate the conversion. - */ - logger.debug("Input type conversion of payload " + message.getPayload() + " resulted in 'null'. " - + "Will use the original message as input."); - } - - convertedInput = message; - } - else { - if (!(convertedInput instanceof Message)) { - convertedInput = MessageBuilder.withPayload(convertedInput).copyHeaders(message.getHeaders()).build(); - } - } - } - return convertedInput; - } - - /** - * This method handles function with multiple output arguments (e.g. Tuple2<..>) - */ - private Object convertMultipleOutputArgumentTypeIfNecesary(Object output, Type type, String[] contentType) { - Type[] outputTypes = ((ParameterizedType) type).getActualTypeArguments(); - Object[] multipleValueArguments = this.parseMultipleValueArguments(output, outputTypes.length); - Object[] convertedOutputs = new Object[outputTypes.length]; - for (int i = 0; i < multipleValueArguments.length; i++) { - String[] ctToUse = !ObjectUtils.isEmpty(contentType) - ? new String[]{contentType[i]} - : new String[] {"application/json"}; - Object convertedInput = this.convertOutputIfNecessary(multipleValueArguments[i], outputTypes[i], ctToUse); - convertedOutputs[i] = convertedInput; - } - return Tuples.fromArray(convertedOutputs); - } - - /* - * - */ - @SuppressWarnings("unchecked") - private Object convertOutputMessageIfNecessary(Object output, String expectedOutputContetntType) { - String contentType = ((Message) output).getHeaders().containsKey(FunctionProperties.EXPECT_CONTENT_TYPE_HEADER) - ? (String) ((Message) output).getHeaders().get(FunctionProperties.EXPECT_CONTENT_TYPE_HEADER) - : expectedOutputContetntType; - - if (StringUtils.hasText(contentType)) { - Map headersMap = new HashMap(((Message) output).getHeaders()); - String[] expectedContentTypes = StringUtils.delimitedListToStringArray(contentType, ","); - for (String expectedContentType : expectedContentTypes) { - headersMap.put(MessageHeaders.CONTENT_TYPE, expectedContentType); - Message message = MessageBuilder.withPayload(((Message) output).getPayload()).copyHeaders(headersMap).build(); - Object result = messageConverter.toMessage(message.getPayload(), message.getHeaders()); - if (result != null) { - return result; - } - } - } - return output; - } - - /** - * This one is used to convert individual value of Collection or array. - */ - @SuppressWarnings("unchecked") - private Object convertMultipleOutputValuesIfNecessary(Object output, String[] contentType) { - Collection outputCollection = ObjectUtils.isArray(output) ? CollectionUtils.arrayToList(output) : (Collection) output; - Collection convertedOutputCollection = outputCollection instanceof List ? new ArrayList<>() : new TreeSet<>(); - Type type = this.isOutputTypeMessage() ? FunctionTypeUtils.getGenericType(this.outputType) : this.outputType; - for (Object outToConvert : outputCollection) { - Object result = this.convertOutputIfNecessary(outToConvert, type, contentType); - Assert.notNull(result, () -> "Failed to convert output '" + outToConvert + "'"); - convertedOutputCollection.add(result); - } - return ObjectUtils.isArray(output) ? convertedOutputCollection.toArray() : convertedOutputCollection; - } - - /* - * - */ - @SuppressWarnings("unchecked") - private Object convertInputPublisherIfNecessary(Publisher publisher, Type type) { - if (FunctionTypeUtils.isMono(type) && publisher instanceof Flux) { - publisher = Mono.from(publisher); - } - else if (FunctionTypeUtils.isFlux(type) && publisher instanceof Mono) { - publisher = Flux.from(publisher); - } - Type actualType = type != null && FunctionTypeUtils.isPublisher(type) - ? FunctionTypeUtils.getImmediateGenericType(type, 0) - : type; - return publisher instanceof Mono - ? Mono.from(publisher).map(v -> { - try { - return this.convertInputIfNecessary(v, actualType == null ? type : actualType); - } - catch (Exception e) { - throw new IllegalStateException("Failed to convert input", e); - } - }) - : Flux.from(publisher).map(v -> { - try { - return this.convertInputIfNecessary(v, actualType == null ? type : actualType); - } - catch (Exception e) { - throw new IllegalStateException("Failed to convert input", e); - } - }); - } - - /* - * - */ - @SuppressWarnings("unchecked") - private Object convertOutputPublisherIfNecessary(Publisher publisher, Type type, String[] expectedOutputContentType) { - return publisher instanceof Mono - ? Mono.from(publisher).map(v -> { - try { - return this.convertOutputIfNecessary(v, type, expectedOutputContentType); - } - catch (Exception e) { - throw new IllegalStateException("Failed to convert output", e); - } - }) - : Flux.from(publisher).map(v -> { - try { - return this.convertOutputIfNecessary(v, type, expectedOutputContentType); - } - catch (Exception e) { - throw new IllegalStateException("Failed to convert output", e); - } - }); - } - } - - /** - * - */ - private static final class OriginalMessageHolder { - private final Object value; - - private final Message originalMessage; - - private OriginalMessageHolder(Object value, Message originalMessage) { - this.value = value; - this.originalMessage = originalMessage; - } - - public Object getValue() { - return this.value; - } - - public Message getOriginalMessage() { - return this.originalMessage; - } - } - - public static class PassThruFunction implements Function { - @Override - public Object apply(Object t) { - return t; - } - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java deleted file mode 100644 index 55299fb99..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2016-2022 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.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import io.cloudevents.spring.messaging.CloudEventMessageConverter; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.function.cloudevent.CloudEventsFunctionInvocationHelper; -import org.springframework.cloud.function.context.DefaultMessageRoutingHandler; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.core.FunctionInvocationHelper; -import org.springframework.cloud.function.json.GsonMapper; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.utils.PrimitiveTypesFromStringMessageConverter; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.ComponentScan.Filter; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; -import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.core.ResolvableType; -import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.core.convert.support.ConfigurableConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.ByteArrayMessageConverter; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.converter.StringMessageConverter; -import org.springframework.stereotype.Component; -import org.springframework.util.ClassUtils; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * @author Dave Syer - * @author Mark Fisher - * @author Oleg Zhurakousky - * @author Artem Bilan - * @author Anshul Mehra - * @author Soby Chacko - * @author Chris Bono - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnMissingBean(FunctionCatalog.class) -@EnableConfigurationProperties(FunctionProperties.class) -@AutoConfigureAfter(name = {"org.springframework.cloud.function.deployer.FunctionDeployerConfiguration"}) -public class ContextFunctionCatalogAutoConfiguration { - - /** - * The name of the property to specify desired JSON mapper. Available values are `jackson' and 'gson'. - */ - public static final String JSON_MAPPER_PROPERTY = "spring.cloud.function.preferred-json-mapper"; - - @Bean - public FunctionRegistry functionCatalog(List messageConverters, JsonMapper jsonMapper, - ConfigurableApplicationContext context, @Nullable FunctionInvocationHelper> functionInvocationHelper) { - ConfigurableConversionService conversionService = (ConfigurableConversionService) context.getBeanFactory().getConversionService(); - if (conversionService == null) { - conversionService = new DefaultConversionService(); - } - Map converters = context.getBeansOfType(GenericConverter.class); - for (GenericConverter converter : converters.values()) { - conversionService.addConverter(converter); - } - - SmartCompositeMessageConverter messageConverter = null; - List mcList = new ArrayList<>(); - - if (!CollectionUtils.isEmpty(messageConverters)) { - for (MessageConverter mc : messageConverters) { - if (mc instanceof CompositeMessageConverter) { - List conv = ((CompositeMessageConverter) mc).getConverters().stream().toList(); - mcList.addAll(conv); - } - else { - mcList.add(mc); - } - } - } - - mcList = mcList.stream() - .filter(this::isConverterEligible) - .collect(Collectors.toList()); - - mcList.add(new JsonMessageConverter(jsonMapper)); - mcList.add(new ByteArrayMessageConverter()); - mcList.add(new StringMessageConverter()); - mcList.add(new PrimitiveTypesFromStringMessageConverter(conversionService)); - - messageConverter = new SmartCompositeMessageConverter(mcList); - if (functionInvocationHelper instanceof CloudEventsFunctionInvocationHelper) { - ((CloudEventsFunctionInvocationHelper) functionInvocationHelper).setMessageConverter(messageConverter); - } - FunctionProperties functionProperties = context.getBean(FunctionProperties.class); - return new BeanFactoryAwareFunctionRegistry(conversionService, messageConverter, jsonMapper, functionProperties, functionInvocationHelper); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Bean(RoutingFunction.FUNCTION_NAME) - public RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties, - BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback, - @Nullable DefaultMessageRoutingHandler defaultMessageRoutingHandler) { - if (defaultMessageRoutingHandler != null) { - FunctionRegistration functionRegistration = new FunctionRegistration(defaultMessageRoutingHandler, RoutingFunction.DEFAULT_ROUTE_HANDLER); - functionRegistration.type(FunctionTypeUtils.consumerType(ResolvableType.forClassWithGenerics(Message.class, Object.class).getType())); - ((FunctionRegistry) functionCatalog).register(functionRegistration); - } - return new RoutingFunction(functionCatalog, functionProperties, new BeanFactoryResolver(beanFactory), routingCallback); - } - - private boolean isConverterEligible(Object messageConverter) { - String messageConverterName = messageConverter.getClass().getName(); - if (messageConverterName.startsWith("org.springframework.cloud.")) { - return true; - } - return !messageConverterName.startsWith("org.springframework."); - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(name = "io.cloudevents.spring.messaging.CloudEventMessageConverter") - static class CloudEventsMessageConverterConfiguration { - - @Bean - @ConditionalOnMissingBean - public CloudEventMessageConverter cloudEventMessageConverter() { - return new CloudEventMessageConverter(); - } - } - - @ComponentScan(basePackages = "${spring.cloud.function.scan.packages:functions}", - includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { Supplier.class, Function.class, Consumer.class }), - excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = { Configuration.class, Component.class})) - @Configuration(proxyBeanMethods = false) - @ConditionalOnProperty(prefix = "spring.cloud.function.scan", name = "enabled", havingValue = "true", matchIfMissing = true) - protected static class PlainFunctionScanConfiguration { - - } - - @Configuration(proxyBeanMethods = false) - public static class JsonMapperConfiguration { - @Bean - public JsonMapper jsonMapper(ApplicationContext context) { - String preferredMapper = context.getEnvironment().getProperty(JSON_MAPPER_PROPERTY); - if (StringUtils.hasText(preferredMapper)) { - if ("gson".equals(preferredMapper) && ClassUtils.isPresent("com.google.gson.Gson", null)) { - return gson(context); - } - else if ("jackson".equals(preferredMapper) && ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { - return jackson(context); - } - } - else { - if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { - return jackson(context); - } - else if (ClassUtils.isPresent("com.google.gson.Gson", null)) { - return gson(context); - } - } - throw new IllegalStateException("Failed to configure JsonMapper. Neither jackson nor gson are present on the claspath"); - } - - private JsonMapper gson(ApplicationContext context) { - Gson gson; - try { - gson = context.getBean(Gson.class); - } - catch (Exception e) { - gson = new Gson(); - } - return new GsonMapper(gson); - } - - private JsonMapper jackson(ApplicationContext context) { - ObjectMapper mapper; - try { - mapper = context.getBean(ObjectMapper.class); - } - catch (Exception e) { - mapper = new ObjectMapper(); - } - return new JacksonMapper(mapper); - } - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java deleted file mode 100644 index b55c28e46..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java +++ /dev/null @@ -1,266 +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.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.cloud.function.utils.PrimitiveTypesFromStringMessageConverter; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.annotation.AnnotationConfigUtils; -import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.type.classreading.MetadataReaderFactory; -import org.springframework.core.type.filter.AssignableTypeFilter; -import org.springframework.format.support.DefaultFormattingConversionService; -import org.springframework.messaging.converter.ByteArrayMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.converter.StringMessageConverter; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -public class ContextFunctionCatalogInitializer implements ApplicationContextInitializer { - - /** - * Property name for ignoring pre initilizer. - */ - public static final String IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME = "spring.backgroundpreinitializer.ignore"; - - /** - * Flag for enabling the context function catalog initializer. - */ - public static boolean enabled = true; - - @Override - public void initialize(GenericApplicationContext applicationContext) { - if (enabled - && applicationContext.getEnvironment().getProperty("spring.functional.enabled", Boolean.class, false)) { - ContextFunctionCatalogBeanRegistrar registrar = new ContextFunctionCatalogBeanRegistrar(applicationContext); - applicationContext.addBeanFactoryPostProcessor(registrar); - } - } - - static class ContextFunctionCatalogBeanRegistrar implements BeanDefinitionRegistryPostProcessor { - - private GenericApplicationContext context; - - ContextFunctionCatalogBeanRegistrar(GenericApplicationContext applicationContext) { - this.context = applicationContext; - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - } - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - try { - register(registry, this.context.getDefaultListableBeanFactory()); - } - catch (BeansException e) { - throw e; - } - catch (RuntimeException e) { - throw e; - } - catch (Exception e) { - throw new BeanCreationException("Cannot register from " + getClass(), e); - } - } - - protected void register(BeanDefinitionRegistry registry, ConfigurableListableBeanFactory factory) - throws Exception { - - performPreinitialization(); - - if (this.context.getBeanFactory().getBeanNamesForType(PropertySourcesPlaceholderConfigurer.class, false, - false).length == 0) { - this.context.registerBean(PropertySourcesPlaceholderConfigurer.class, - () -> PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer()); - } - - if (!this.context.getBeanFactory() - .containsBeanDefinition(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { - // Switch off the ConfigurationClassPostProcessor - this.context.registerBean(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME, - DummyProcessor.class, () -> new DummyProcessor()); - // But switch on other annotation processing - AnnotationConfigUtils.registerAnnotationConfigProcessors(this.context); - } - ConfigurationPropertiesBindingPostProcessor.register(registry); - - String preferredMapper = context.getEnvironment().getProperty(ContextFunctionCatalogAutoConfiguration.JSON_MAPPER_PROPERTY); - - if (ClassUtils.isPresent("com.google.gson.Gson", null) && "gson".equals(preferredMapper)) { - if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false, false).length == 0) { - this.context.registerBean(Gson.class, () -> new Gson()); - } - this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context)); - } - else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { - if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class, false, false).length == 0) { - this.context.registerBean(ObjectMapper.class, () -> new ObjectMapper()); - } - this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context)); - - } - - String basePackage = this.context.getEnvironment().getProperty("spring.cloud.function.scan.packages", - "functions"); - if (this.context.getEnvironment().getProperty("spring.cloud.function.scan.enabled", Boolean.class, true) - && new ClassPathResource(basePackage.replace(".", "/")).exists()) { - ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.context, false, - this.context.getEnvironment(), this.context); - scanner.addIncludeFilter(new AssignableTypeFilter(Function.class)); - scanner.addIncludeFilter(new AssignableTypeFilter(Supplier.class)); - scanner.addIncludeFilter(new AssignableTypeFilter(Consumer.class)); - for (BeanDefinition bean : scanner.findCandidateComponents(basePackage)) { - String name = bean.getBeanClassName(); - Class type = ClassUtils.resolveClassName(name, this.context.getClassLoader()); - this.context.registerBeanDefinition(name, bean); - this.context.registerBean("registration_" + name, FunctionRegistration.class, - () -> new FunctionRegistration<>(this.context.getBean(name), name).type(type)); - } - } - - if (this.context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class, false, false).length == 0) { - this.context.registerBean(SimpleFunctionRegistry.class, () -> { - List messageConverters = new ArrayList<>(); - JsonMapper jsonMapper = this.context.getBean(JsonMapper.class); - - messageConverters.addAll(context.getBeansOfType(MessageConverter.class).values()); - messageConverters.add(new JsonMessageConverter(jsonMapper)); - messageConverters.add(new ByteArrayMessageConverter()); - messageConverters.add(new StringMessageConverter()); - messageConverters.add(new PrimitiveTypesFromStringMessageConverter(new DefaultConversionService())); - - SmartCompositeMessageConverter messageConverter = new SmartCompositeMessageConverter(messageConverters); - - ConversionService conversionService = new DefaultConversionService(); - return new SimpleFunctionRegistry(conversionService, messageConverter, this.context.getBean(JsonMapper.class)); - }); - this.context.registerBean(FunctionProperties.class, () -> new FunctionProperties()); - this.context.registerBean(FunctionRegistrationPostProcessor.class, - () -> new FunctionRegistrationPostProcessor(this.context.getAutowireCapableBeanFactory() - .getBeanProvider(FunctionRegistration.class))); - } - } - - private void performPreinitialization() { - if (Boolean.getBoolean(IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME)) { - return; - } - try { - Thread thread = new Thread(new Runnable() { - - @Override - public void run() { - runSafely(() -> new DefaultFormattingConversionService()); - } - - public void runSafely(Runnable runnable) { - try { - runnable.run(); - } - catch (Throwable ex) { - // Ignore - } - } - - }, "background-preinit"); - thread.start(); - } - catch (Exception ex) { - } - } - - private class FunctionRegistrationPostProcessor implements BeanPostProcessor { - - @SuppressWarnings("rawtypes") - private final ObjectProvider functions; - - FunctionRegistrationPostProcessor( - @SuppressWarnings("rawtypes") ObjectProvider functions) { - this.functions = functions; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof FunctionRegistry) { - FunctionRegistry catalog = (FunctionRegistry) bean; - for (FunctionRegistration registration : this.functions) { - Assert.notEmpty(registration.getNames(), - "FunctionRegistration must define at least one name. Was empty"); - if (registration.getType() == null) { - throw new IllegalStateException( - "You need an explicit type for the function: " + registration.getNames()); - // TODO: in principle Spring could know how to extract this - // from the supplier, but in practice there is no functional - // bean registration with parametric types. - } - catalog.register(registration); - } - } - return bean; - } - - } - - } - - /** - * Dummy implementation of a processor. - */ - public static class DummyProcessor { - - public void setMetadataReaderFactory(MetadataReaderFactory obj) { - } - - } - -} 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 deleted file mode 100644 index 46a501436..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionContextUtils.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2012-2022 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.config; - -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -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.core.io.Resource; -import org.springframework.core.type.MethodMetadata; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -/** - * @author Oleg Zhurakousky - * @since 2.0 - */ -public abstract class FunctionContextUtils { - - public static Type findType(String name, ConfigurableListableBeanFactory registry) { - return findType(registry, name); - } - - public static Type findType(ConfigurableListableBeanFactory registry, String... names) { - AbstractBeanDefinition definition = null; - String actualName = null; - for (String name : names) { - if (registry.containsBeanDefinition(name)) { - definition = (AbstractBeanDefinition) registry.getBeanDefinition(name); - actualName = name; - } - else if (registry.containsBean(name)) { - return FunctionTypeUtils.discoverFunctionTypeFromClass(registry.getBean(name).getClass()); - } - } - - Class beanClass = null; - - - if (definition == null) { - return null; - } - else { - beanClass = resolveBeanClass(definition); - } - - Object source = definition.getSource(); - - Type param = null; - if (source instanceof MethodMetadata) { - param = findBeanType(definition, ((MethodMetadata) source).getDeclaringClassName(), ((MethodMetadata) source).getMethodName()); - } - else if (source instanceof Resource) { - param = registry.getType(actualName); - } - - if (param == null) { - param = definition.getResolvableType().getType(); - } - - if (!(param instanceof ParameterizedType) && beanClass != null) { - return FunctionTypeUtils.discoverFunctionTypeFromClass(beanClass); - } - return param; - } - - public static Class[] getParamTypesFromBeanDefinitionFactory(Class factory, - AbstractBeanDefinition definition) { - if (definition instanceof RootBeanDefinition) { - RootBeanDefinition root = (RootBeanDefinition) definition; - for (Method method : getCandidateMethods(factory, root)) { - if (root.isFactoryMethod(method)) { - return method.getParameterTypes(); - } - } - } - List> params = new ArrayList<>(); - for (ConstructorArgumentValues.ValueHolder holder : definition - .getConstructorArgumentValues().getIndexedArgumentValues().values()) { - params.add(ClassUtils.resolveClassName(holder.getType(), null)); - } - return params.toArray(new Class[0]); - } - - private static Class resolveBeanClass(AbstractBeanDefinition beanDefinition) { - try { - return beanDefinition.hasBeanClass() ? beanDefinition.getBeanClass() : ClassUtils.getDefaultClassLoader().loadClass(beanDefinition.getBeanClassName()); - } - catch (Exception e) { - return null; - } - } - - private static Type findBeanType(AbstractBeanDefinition definition, String declaringClassName, String methodName) { - Class factory = ClassUtils.resolveClassName(declaringClassName, null); - Class[] params = getParamTypesFromBeanDefinitionFactory(factory, definition); - Method method = ReflectionUtils.findMethod(factory, methodName, - params); - Type type = method.getGenericReturnType(); - return type; - } - - private static Method[] getCandidateMethods(final Class factoryClass, - final RootBeanDefinition mbd) { - return (mbd.isNonPublicAccessAllowed() - ? ReflectionUtils.getAllDeclaredMethods(factoryClass) - : factoryClass.getMethods()); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionsEndpointAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionsEndpointAutoConfiguration.java deleted file mode 100644 index 861b50c5c..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/FunctionsEndpointAutoConfiguration.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021-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.context.config; - -import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.function.actuator.FunctionsEndpoint; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Oleg Zhurakousky - * @since 3.2 - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass(name = { - "org.springframework.boot.actuate.endpoint.annotation.Endpoint" }) -@ConditionalOnBean(FunctionCatalog.class) -@AutoConfigureAfter(EndpointAutoConfiguration.class) -public class FunctionsEndpointAutoConfiguration { - - @Bean - @ConditionalOnAvailableEndpoint - public FunctionsEndpoint functionsEndpoint(FunctionCatalog functionCatalog) { - return new FunctionsEndpoint(functionCatalog); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/JsonMessageConverter.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/JsonMessageConverter.java deleted file mode 100644 index 961620119..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/JsonMessageConverter.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2020-2022 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.config; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; - -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.core.GenericTypeResolver; -import org.springframework.core.MethodParameter; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.util.MimeType; -import org.springframework.util.StringUtils; - -/** - * Implementation of {@link MessageConverter} which uses Jackson or Gson libraries to do the - * actual conversion via {@link JsonMapper} instance. - * - * @author Oleg Zhurakousky - * @author Andrey Shlykov - * - * @since 3.0.4 - */ -public class JsonMessageConverter extends AbstractMessageConverter { - - private final JsonMapper jsonMapper; - - public JsonMessageConverter(JsonMapper jsonMapper) { - this(jsonMapper, new MimeType("application", "json"), new MimeType(CloudEventMessageUtils.APPLICATION_CLOUDEVENTS.getType(), - CloudEventMessageUtils.APPLICATION_CLOUDEVENTS.getSubtype() + "+json")); - } - - public JsonMessageConverter(JsonMapper jsonMapper, MimeType... supportedMimeTypes) { - super(supportedMimeTypes); - this.jsonMapper = jsonMapper; - } - - @Override - protected boolean supports(Class clazz) { - // should not be called, since we override canConvertFrom/canConvertTo instead - throw new UnsupportedOperationException(); - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - if (!supportsMimeType(headers)) { - return false; - } - return true; - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - return supportsMimeType(message.getHeaders()) && this.canDiscoverConvertToType(message, targetClass); - } - - private boolean canDiscoverConvertToType(Message message, Class targetClass) { - if (targetClass == null || targetClass == Object.class) { - MimeType mimeType = getMimeType(message.getHeaders()); - if (StringUtils.hasText(mimeType.getParameter("type"))) { - return true; - } - return false; - } - return true; - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, @Nullable Object conversionHint) { - if (conversionHint instanceof ParameterizedTypeReference) { - conversionHint = ((ParameterizedTypeReference) conversionHint).getType(); - } - Type convertToType = this.getResolvedType(targetClass, conversionHint); - if (convertToType == null || convertToType == Object.class) { - MimeType mimeType = getMimeType(message.getHeaders()); - String type = mimeType.getParameter("type"); - if (StringUtils.hasText(type)) { - try { - convertToType = Thread.currentThread().getContextClassLoader().loadClass(type); - } - catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Failed to load class `" + type + "` specified by the provided content-type: " + mimeType, e); - } - } - else { - return message.getPayload(); - } - } - if (targetClass == byte[].class && message.getPayload() instanceof String) { - return ((String) message.getPayload()).getBytes(StandardCharsets.UTF_8); - } - else { - try { - return this.jsonMapper.fromJson(message.getPayload(), convertToType); - } - catch (Exception e) { - if (message.getPayload() instanceof byte[] && String.class.isAssignableFrom(targetClass)) { - return new String((byte[]) message.getPayload(), StandardCharsets.UTF_8); - } - else if (logger.isDebugEnabled()) { - Object payload = message.getPayload(); - if (payload instanceof byte[]) { - payload = new String((byte[]) payload, StandardCharsets.UTF_8); - } - - if (logger.isDebugEnabled()) { - logger.debug("Failed to convert value: " + payload + " to: " + targetClass, e); - } - else { - logger.warn("Failed to convert value: " + payload + " to: " + targetClass); - } - } - } - } - - return null; - } - - @Override - protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, - @Nullable Object conversionHint) { - return jsonMapper.toJson(payload); - } - - private Type getResolvedType(Class targetClass, @Nullable Object conversionHint) { - if (conversionHint instanceof MethodParameter param) { - param = param.nestedIfOptional(); - if (Message.class.isAssignableFrom(param.getParameterType())) { - param = param.nested(); - } - Type genericParameterType = param.getNestedGenericParameterType(); - Class contextClass = param.getContainingClass(); - return GenericTypeResolver.resolveType(genericParameterType, contextClass); - } - else if (conversionHint instanceof ParameterizedType) { - return (Type) conversionHint; - } - return targetClass; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java deleted file mode 100644 index 034a6b883..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2012-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.context.config; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.fasterxml.jackson.module.kotlin.KotlinModule; -import kotlin.Unit; -import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; -import kotlin.jvm.functions.Function2; -import kotlin.jvm.functions.Function3; -import kotlin.jvm.functions.Function4; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.ResolvableType; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.util.ObjectUtils; - -/** - * Configuration class which defines the required infrastructure to bootstrap Kotlin - * lambdas as invocable functions within the context of the framework. - * - * @author Oleg Zhurakousky - * @author Adrien Poupard - * @author Dmitriy Tsypov - * @since 2.0 - */ -@Configuration -@ConditionalOnClass(name = "kotlin.jvm.functions.Function0") -public class KotlinLambdaToFunctionAutoConfiguration { - - protected final Log logger = LogFactory.getLog(getClass()); - - @Bean - @ConditionalOnMissingBean - @ConditionalOnClass(name = {"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder", - "com.fasterxml.jackson.module.kotlin.KotlinModule"}) - Jackson2ObjectMapperBuilderCustomizer customizer() { - return new Jackson2ObjectMapperBuilderCustomizer() { - @Override - public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { - jacksonObjectMapperBuilder.modulesToInstall(KotlinModule.class); - } - }; - } - - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final class KotlinFunctionWrapper implements Function, Supplier, Consumer, - Function0, Function1, Function2, - Function3, Function4 { - private final Object kotlinLambdaTarget; - - private String name; - - private ConfigurableListableBeanFactory beanFactory; - - public KotlinFunctionWrapper(Object kotlinLambdaTarget) { - this.kotlinLambdaTarget = kotlinLambdaTarget; - } - - @Override - public Object apply(Object input) { - if (ObjectUtils.isEmpty(input)) { - return this.invoke(); - } - else { - return this.invoke(input); - } - } - - @Override - public Object invoke(Object arg0, Object arg1, Object arg2, Object arg3) { - return ((Function4) this.kotlinLambdaTarget).invoke(arg0, arg1, arg2, arg3); - } - - @Override - public Object invoke(Object arg0, Object arg1, Object arg2) { - return ((Function3) this.kotlinLambdaTarget).invoke(arg0, arg1, arg2); - } - - @Override - public Object invoke(Object arg0, Object arg1) { - return ((Function2) this.kotlinLambdaTarget).invoke(arg0, arg1); - } - - @Override - public Object invoke(Object arg0) { - if (CoroutinesUtils.isValidSuspendingFunction(kotlinLambdaTarget, arg0)) { - return CoroutinesUtils.invokeSuspendingFunction(kotlinLambdaTarget, arg0); - } - if (this.kotlinLambdaTarget instanceof Function1) { - return ((Function1) this.kotlinLambdaTarget).invoke(arg0); - } - return ((Function) this.kotlinLambdaTarget).apply(arg0); - } - - @Override - public Object invoke() { - if (CoroutinesUtils.isValidSuspendingSupplier(kotlinLambdaTarget)) { - return CoroutinesUtils.invokeSuspendingSupplier(kotlinLambdaTarget); - } - if (this.kotlinLambdaTarget instanceof Function0) { - return ((Function0) this.kotlinLambdaTarget).invoke(); - } - return ((Supplier) this.kotlinLambdaTarget).get(); - } - - @Override - public void accept(Object input) { - if (CoroutinesUtils.isValidSuspendingFunction(kotlinLambdaTarget, input)) { - CoroutinesUtils.invokeSuspendingConsumer(kotlinLambdaTarget, input); - return; - } - this.apply(input); - } - - @Override - public Object get() { - return this.apply(null); - } - - public FunctionRegistration getFunctionRegistration() { - String name = this.name.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) - ? this.name.replace(FunctionRegistration.REGISTRATION_NAME_SUFFIX, "") - : this.name; - Type functionType = FunctionContextUtils.findType(name, this.beanFactory); - FunctionRegistration registration = new FunctionRegistration<>(this, name); - Type[] types = ((ParameterizedType) functionType).getActualTypeArguments(); - - if (isValidKotlinSupplier(functionType)) { - functionType = ResolvableType.forClassWithGenerics(Supplier.class, ResolvableType.forType(types[0])) - .getType(); - } - else if (isValidKotlinConsumer(functionType, types)) { - functionType = ResolvableType.forClassWithGenerics(Consumer.class, ResolvableType.forType(types[0])) - .getType(); - } - else if (isValidKotlinFunction(functionType, types)) { - functionType = ResolvableType.forClassWithGenerics(Function.class, ResolvableType.forType(types[0]), - ResolvableType.forType(types[1])).getType(); - } - else if (isValidKotlinSuspendSupplier(functionType, types)) { - Type continuationReturnType = CoroutinesUtils.getSuspendingFunctionReturnType(types[0]); - functionType = ResolvableType.forClassWithGenerics( - Supplier.class, - ResolvableType.forClassWithGenerics(Flux.class, ResolvableType.forType(continuationReturnType)) - ).getType(); - } - else if (isValidKotlinSuspendFunction(functionType, types)) { - Type continuationArgType = CoroutinesUtils.getSuspendingFunctionArgType(types[0]); - Type continuationReturnType = CoroutinesUtils.getSuspendingFunctionReturnType(types[1]); - functionType = ResolvableType.forClassWithGenerics( - Function.class, - ResolvableType.forClassWithGenerics(Flux.class, ResolvableType.forType(continuationArgType)), - ResolvableType.forClassWithGenerics(Flux.class, ResolvableType.forType(continuationReturnType)) - ).getType(); - } - else if (isValidKotlinSuspendConsumer(functionType, types)) { - Type continuationArgType = CoroutinesUtils.getSuspendingFunctionArgType(types[0]); - functionType = ResolvableType.forClassWithGenerics( - Consumer.class, - ResolvableType.forClassWithGenerics(Flux.class, ResolvableType.forType(continuationArgType)) - ).getType(); - } - else if (!FunctionTypeUtils.isFunction(functionType) - && !FunctionTypeUtils.isConsumer(functionType) - && !FunctionTypeUtils.isSupplier(functionType)) { - throw new UnsupportedOperationException("Multi argument Kotlin functions are not currently supported"); - } - registration = registration.type(functionType); - return registration; - } - - private boolean isValidKotlinSupplier(Type functionType) { - return isTypeRepresentedByClass(functionType, Function0.class); - } - - private boolean isValidKotlinConsumer(Type functionType, Type[] type) { - return isTypeRepresentedByClass(functionType, Function1.class) && - type.length == 2 && - !CoroutinesUtils.isContinuationType(type[0]) && - isTypeRepresentedByClass(type[1], Unit.class); - } - - private boolean isValidKotlinFunction(Type functionType, Type[] type) { - return isTypeRepresentedByClass(functionType, Function1.class) && - type.length == 2 && - !CoroutinesUtils.isContinuationType(type[0]) && - !isTypeRepresentedByClass(type[1], Unit.class); - } - - private boolean isValidKotlinSuspendSupplier(Type functionType, Type[] type) { - return isTypeRepresentedByClass(functionType, Function1.class) && - type.length == 2 && - CoroutinesUtils.isContinuationFlowType(type[0]); - } - - private boolean isValidKotlinSuspendConsumer(Type functionType, Type[] type) { - return isTypeRepresentedByClass(functionType, Function2.class) && - type.length == 3 && - CoroutinesUtils.isFlowType(type[0]) && - CoroutinesUtils.isContinuationUnitType(type[1]); - } - - private boolean isValidKotlinSuspendFunction(Type functionType, Type[] type) { - return isTypeRepresentedByClass(functionType, Function2.class) && - type.length == 3 && - CoroutinesUtils.isContinuationFlowType(type[1]); - } - - private boolean isTypeRepresentedByClass(Type type, Class clazz) { - return type.getTypeName().contains(clazz.getName()); - } - - public Class getObjectType() { - return FunctionRegistration.class; - } - - - public void setName(String name) { - this.name = name; - } - - - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; - } - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java deleted file mode 100644 index 53b134ca9..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java +++ /dev/null @@ -1,244 +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.context.config; - -import java.util.Map; -import java.util.function.Function; - -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.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.context.expression.MapAccessor; -import org.springframework.expression.BeanResolver; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.DataBindingPropertyAccessor; -import org.springframework.expression.spel.support.SimpleEvaluationContext; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * An implementation of Function which acts as a gateway/router by actually - * delegating incoming invocation to a function specified .. . - * - * @author Oleg Zhurakousky - * @since 2.1 - * - */ -//TODO - perhaps change to Function, Message> -public class RoutingFunction implements Function { - - /** - * The name of this function use by BeanFactory. - */ - public static final String FUNCTION_NAME = "functionRouter"; - - /** - * The name of this function for routing of un-routable messages. - */ - public static final String DEFAULT_ROUTE_HANDLER = "defaultMessageRoutingHandler"; - - private static Log logger = LogFactory.getLog(RoutingFunction.class); - - private final StandardEvaluationContext evalContext = new StandardEvaluationContext(); - - private final SimpleEvaluationContext headerEvalContext = SimpleEvaluationContext - .forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess()).build(); - - private final SpelExpressionParser spelParser = new SpelExpressionParser(); - - private final FunctionCatalog functionCatalog; - - private final FunctionProperties functionProperties; - - private final MessageRoutingCallback routingCallback; - - public RoutingFunction(FunctionCatalog functionCatalog, FunctionProperties functionProperties) { - this(functionCatalog, functionProperties, null, null); - } - - public RoutingFunction(FunctionCatalog functionCatalog, Map propertiesMap, - BeanResolver beanResolver, MessageRoutingCallback routingCallback) { - this(functionCatalog, extractIntoFunctionProperties(propertiesMap), beanResolver, routingCallback); - } - - public RoutingFunction(FunctionCatalog functionCatalog, FunctionProperties functionProperties, - BeanResolver beanResolver, MessageRoutingCallback routingCallback) { - this.functionCatalog = functionCatalog; - this.functionProperties = functionProperties; - this.routingCallback = routingCallback; - this.evalContext.addPropertyAccessor(new MapAccessor()); - evalContext.setBeanResolver(beanResolver); - } - - private static FunctionProperties extractIntoFunctionProperties(Map propertiesMap) { - FunctionProperties functionProperties = new FunctionProperties(); - functionProperties.setDefinition(propertiesMap.get(FunctionProperties.FUNCTION_DEFINITION)); - functionProperties.setRoutingExpression(propertiesMap.get(FunctionProperties.ROUTING_EXPRESSION)); - return functionProperties; - } - - @Override - public Object apply(Object input) { - return this.route(input, input instanceof Publisher); - } - - - /* - * - Check if `this.routingCallback` is present and if it is use it (only for Message input) - * If NOT - * - Check if spring.cloud.function.definition is set in header and if it is use it.(only for Message input) - * If NOT - * - Check if spring.cloud.function.routing-expression is set in header and if it is set use it (only for Message input) - * If NOT - * - Check `spring.cloud.function.definition` is set in FunctionProperties and if it is use it (Message and Publisher) - * If NOT - * - Check `spring.cloud.function.routing-expression` is set in FunctionProperties and if it is use it (Message and Publisher) - * If NOT - * - Fail - */ - private Object route(Object input, boolean originalInputIsPublisher) { - FunctionInvocationWrapper function = null; - - if (input instanceof Message) { - Message message = (Message) input; - if (this.routingCallback != null) { - String functionDefinition = this.routingCallback.routingResult(message); - if (StringUtils.hasText(functionDefinition)) { - function = this.functionFromDefinition(functionDefinition); - } - } - if (function == null) { - if (StringUtils.hasText((String) message.getHeaders().get(FunctionProperties.FUNCTION_DEFINITION))) { - function = functionFromDefinition((String) message.getHeaders().get(FunctionProperties.FUNCTION_DEFINITION)); - if (function.isInputTypePublisher()) { - this.assertOriginalInputIsNotPublisher(originalInputIsPublisher); - } - } - else if (StringUtils.hasText((String) message.getHeaders().get(FunctionProperties.ROUTING_EXPRESSION))) { - function = this.functionFromExpression((String) message.getHeaders().get(FunctionProperties.ROUTING_EXPRESSION), message, true); - if (function.isInputTypePublisher()) { - this.assertOriginalInputIsNotPublisher(originalInputIsPublisher); - } - } - else if (StringUtils.hasText(functionProperties.getRoutingExpression())) { - function = this.functionFromExpression(functionProperties.getRoutingExpression(), message); - } - else if (StringUtils.hasText(functionProperties.getDefinition())) { - function = this.functionFromDefinition(functionProperties.getDefinition()); - } - else { - throw new IllegalStateException("Failed to establish route, since neither were provided: " - + "'spring.cloud.function.definition' as Message header or as application property or " - + "'spring.cloud.function.routing-expression' as application property. Incoming message: " + input); - } - } - } - else if (input instanceof Publisher) { - if (StringUtils.hasText(functionProperties.getDefinition())) { - function = functionFromDefinition(functionProperties.getDefinition()); - } - else if (StringUtils.hasText(functionProperties.getRoutingExpression())) { - function = this.functionFromExpression(functionProperties.getRoutingExpression(), input); - } - else { - return input instanceof Mono - ? Mono.from((Publisher) input).map(v -> route(v, originalInputIsPublisher)) - : Flux.from((Publisher) input).map(v -> route(v, originalInputIsPublisher)); - } - } - else { - this.assertOriginalInputIsNotPublisher(originalInputIsPublisher); - if (StringUtils.hasText(functionProperties.getRoutingExpression())) { - function = this.functionFromExpression(functionProperties.getRoutingExpression(), input); - } - else - if (StringUtils.hasText(functionProperties.getDefinition())) { - function = functionFromDefinition(functionProperties.getDefinition()); - } - else { - throw new IllegalStateException("Failed to establish route, since neither were provided: " - + "'spring.cloud.function.definition' as Message header or as application property or " - + "'spring.cloud.function.routing-expression' as application property."); - } - } - - if (function.getTarget().equals(this)) { - throw new IllegalStateException("Failed to establish route, and routing to itself is not allowed as it creates a loop. Please provide: " - + "'spring.cloud.function.definition' as Message header or as application property or " - + "'spring.cloud.function.routing-expression' as application property."); - } - - return function.apply(input); - } - - private void assertOriginalInputIsNotPublisher(boolean originalInputIsPublisher) { - Assert.isTrue(!originalInputIsPublisher, "Routing input of type Publisher is not supported per individual " - + "values (e.g., message header or POJO). Instead you should use 'spring.cloud.function.definition' or " - + "spring.cloud.function.routing-expression' as application properties."); - } - - private FunctionInvocationWrapper functionFromDefinition(String definition) { - FunctionInvocationWrapper function = this.resolveFunction(definition); - Assert.notNull(function, "Failed to lookup function to route based on the value of 'spring.cloud.function.definition' property '" - + functionProperties.getDefinition() + "'"); - if (logger.isInfoEnabled()) { - logger.info("Resolved function from provided [definition] property " + functionProperties.getDefinition()); - } - return function; - } - - private FunctionInvocationWrapper functionFromExpression(String routingExpression, Object input) { - return functionFromExpression(routingExpression, input, false); - } - - private FunctionInvocationWrapper functionFromExpression(String routingExpression, Object input, boolean isViaHeader) { - Expression expression = spelParser.parseExpression(routingExpression); - if (input instanceof Message) { - input = MessageUtils.toCaseInsensitiveHeadersStructure((Message) input); - } - - String definition = isViaHeader ? expression.getValue(this.headerEvalContext, input, String.class) : expression.getValue(this.evalContext, input, String.class); - Assert.hasText(definition, "Failed to resolve function name based on routing expression '" + functionProperties.getRoutingExpression() + "'"); - FunctionInvocationWrapper function = this.resolveFunction(definition); - Assert.notNull(function, "Failed to lookup function to route to based on the expression '" - + functionProperties.getRoutingExpression() + "' which resolved to '" + definition + "' function definition."); - if (logger.isInfoEnabled()) { - logger.info("Resolved function from provided [routing-expression] " + routingExpression); - } - return function; - } - - private FunctionInvocationWrapper resolveFunction(String definition) { - FunctionInvocationWrapper function = functionCatalog.lookup(definition); - if (function == null) { - function = functionCatalog.lookup(RoutingFunction.DEFAULT_ROUTE_HANDLER); - } - return function; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/SmartCompositeMessageConverter.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/SmartCompositeMessageConverter.java deleted file mode 100644 index 12c3bdf0a..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/SmartCompositeMessageConverter.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2020-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.config; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.converter.SmartMessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.messaging.support.MessageHeaderAccessor; -import org.springframework.util.MimeType; -import org.springframework.util.StringUtils; - -/** - * - * @author Oleg Zhurakousky - * @author Salvatore Bernardo - * - */ -public class SmartCompositeMessageConverter extends CompositeMessageConverter { - - private Log logger = LogFactory.getLog(this.getClass()); - - public SmartCompositeMessageConverter(Collection converters) { - super(converters); - } - - @Override - @Nullable - public Object fromMessage(Message message, Class targetClass) { - for (MessageConverter converter : getConverters()) { - if (!(message.getPayload() instanceof byte[]) && targetClass.isInstance(message.getPayload()) && !(message.getPayload() instanceof Collection)) { - return message.getPayload(); - } - try { - Object result = converter.fromMessage(message, targetClass); - if (result != null) { - return result; - } - } - catch (Exception e) { - if (logger.isWarnEnabled()) { - logger.warn("Failure during type conversion by " + converter + ". Will try the next converter.", e); - } - } - } - return null; - } - - @SuppressWarnings("unchecked") - @Override - public Object fromMessage(Message message, Class targetClass, @Nullable Object conversionHint) { - if (!(message.getPayload() instanceof byte[]) && targetClass.isInstance(message.getPayload()) && !(message.getPayload() instanceof Collection)) { - return message.getPayload(); - } - Object result = null; - if (message.getPayload() instanceof Iterable && conversionHint != null) { - Iterable iterablePayload = (Iterable) message.getPayload(); - Type genericItemType = FunctionTypeUtils.getImmediateGenericType((Type) conversionHint, 0); - Class genericItemRawType = FunctionTypeUtils.getRawType(genericItemType); - List resultList = new ArrayList<>(); - for (Object item : iterablePayload) { - boolean isConverted = false; - if (item.getClass().getName().startsWith("org.springframework.kafka.support.KafkaNull")) { - resultList.add(null); - isConverted = true; - } - for (Iterator iterator = getConverters().iterator(); iterator.hasNext() && !isConverted;) { - MessageConverter converter = (MessageConverter) iterator.next(); - if (!converter.getClass().getName().endsWith("ApplicationJsonMessageMarshallingConverter")) { // TODO Stream stuff, needs to be removed - Message m = MessageBuilder.withPayload(item).copyHeaders(message.getHeaders()).build(); // TODO Message creating may be expensive - Object conversionResult = (converter instanceof SmartMessageConverter & genericItemRawType != genericItemType ? - ((SmartMessageConverter) converter).fromMessage(m, genericItemRawType, genericItemType) : - converter.fromMessage(m, genericItemRawType)); - if (conversionResult != null) { - resultList.add(conversionResult); - isConverted = true; - } - } - } - } - result = resultList; - } - else { - for (MessageConverter converter : getConverters()) { - if (!converter.getClass().getName().endsWith("ApplicationJsonMessageMarshallingConverter")) { // TODO Stream stuff, needs to be removed - result = (converter instanceof SmartMessageConverter ? - ((SmartMessageConverter) converter).fromMessage(message, targetClass, conversionHint) : - converter.fromMessage(message, targetClass)); - if (result != null) { - return result; - } - } - } - } - - return result; - } - - @Override - @Nullable - public Message toMessage(Object payload, @Nullable MessageHeaders headers) { - for (MessageConverter converter : getConverters()) { - if (headers.get(MessageHeaders.CONTENT_TYPE) == null) { - return null; - } - - Object value = headers.get(MessageHeaders.CONTENT_TYPE).toString(); - String[] contentTypes = StringUtils.delimitedListToStringArray((String) value, ","); - for (String contentType : contentTypes) { - if (!MimeType.valueOf(contentType).isConcrete()) { - if (converter instanceof AbstractMessageConverter) { - List supportedMimeTypes = ((AbstractMessageConverter) converter).getSupportedMimeTypes(); - for (MimeType supportedMimeType : supportedMimeTypes) { - if (supportedMimeType.isCompatibleWith(MimeType.valueOf(contentType))) { - MessageHeaderAccessor h = new MessageHeaderAccessor(); - h.copyHeaders(headers); - h.setHeader(MessageHeaders.CONTENT_TYPE, supportedMimeType); - Message result = converter.toMessage(payload, h.getMessageHeaders()); - if (result != null) { - return result; - } - } - } - } - } - else { - MessageHeaderAccessor h = new MessageHeaderAccessor(); - h.copyHeaders(headers); - h.setHeader(MessageHeaders.CONTENT_TYPE, contentType); - Message result = converter.toMessage(payload, h.getMessageHeaders()); - if (result != null) { - return result; - } - } - } - } - return null; - } - - @Override - @Nullable - public Message toMessage(Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - for (MessageConverter converter : getConverters()) { - Object value = headers.get(MessageHeaders.CONTENT_TYPE).toString(); - String[] contentTypes = StringUtils.delimitedListToStringArray((String) value, ","); - for (String contentType : contentTypes) { - if (!MimeType.valueOf(contentType).isConcrete()) { - List supportedMimeTypes = ((AbstractMessageConverter) converter).getSupportedMimeTypes(); - for (MimeType supportedMimeType : supportedMimeTypes) { - MessageHeaderAccessor h = new MessageHeaderAccessor(); - h.copyHeaders(headers); - h.setHeader(MessageHeaders.CONTENT_TYPE, supportedMimeType); - Message result = ((SmartMessageConverter) converter).toMessage(payload, h.getMessageHeaders(), conversionHint); - if (result != null) { - return result; - } - } - } - else { - MessageHeaderAccessor h = new MessageHeaderAccessor(); - h.copyHeaders(headers); - h.setHeader(MessageHeaders.CONTENT_TYPE, contentType); - Message result = ((SmartMessageConverter) converter).toMessage(payload, h.getMessageHeaders(), conversionHint); - if (result != null) { - return result; - } - } - } - } - return null; - } -} 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 deleted file mode 100644 index 6bfdbf952..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/message/MessageUtils.java +++ /dev/null @@ -1,74 +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.message; - -import java.util.Map; -import java.util.TreeMap; - -import org.springframework.messaging.Message; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public abstract class MessageUtils { - - /** - * Value for 'message-type' typically use as header key. - */ - public static String MESSAGE_TYPE = "message-type"; - - /** - * Value for 'target-protocol' typically use as header key. - */ - public static String TARGET_PROTOCOL = "target-protocol"; - - /** - * Value for 'target-protocol' typically use as header key. - */ - public static String SOURCE_TYPE = "source-type"; - - /** - * Returns (payload, headers) structure identical to `message` while substituting headers with case insensitive map. - */ - public static MessageStructureWithCaseInsensitiveHeaderKeys toCaseInsensitiveHeadersStructure(Message message) { - return new MessageStructureWithCaseInsensitiveHeaderKeys(message); - } - - /** - * !!! INTERNAL USE ONLY, MAY CHANGE OR REMOVED WITHOUT NOTICE!!! - */ - @SuppressWarnings({"rawtypes"}) - public static class MessageStructureWithCaseInsensitiveHeaderKeys { - private final Object payload; - private final Map headers; - - @SuppressWarnings("unchecked") - MessageStructureWithCaseInsensitiveHeaderKeys(Message message) { - this.payload = message.getPayload(); - this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - this.headers.putAll(message.getHeaders()); - } - public Object getPayload() { - return payload; - } - - public Map getHeaders() { - return headers; - } - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalSpringBootTest.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalSpringBootTest.java deleted file mode 100644 index 1642146be..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalSpringBootTest.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.context.test; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.core.annotation.AliasFor; -import org.springframework.test.context.ContextConfiguration; - -/** - * - * @author Dave Syer - * @since 2.0 - * - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@SpringBootTest(properties = "spring.functional.enabled=true") -@ContextConfiguration(loader = FunctionalTestContextLoader.class) -public @interface FunctionalSpringBootTest { - - @AliasFor(annotation = SpringBootTest.class, attribute = "properties") - String[] value() default {}; - - @AliasFor(annotation = SpringBootTest.class, attribute = "value") - String[] properties() default {}; - - @AliasFor(annotation = SpringBootTest.class, attribute = "classes") - Class[] classes() default {}; - - @AliasFor(annotation = SpringBootTest.class, attribute = "webEnvironment") - WebEnvironment webEnvironment() default WebEnvironment.MOCK; - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalTestContextLoader.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalTestContextLoader.java deleted file mode 100644 index 8193960e1..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/test/FunctionalTestContextLoader.java +++ /dev/null @@ -1,38 +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.test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.test.context.SpringBootContextLoader; -import org.springframework.cloud.function.context.FunctionalSpringApplication; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer; - -/** - * A test context loader for Spring Boot applications that use the - * {@link ContextFunctionCatalogInitializer}. - * - * @author Dave Syer - * @since 2.0 - */ -class FunctionalTestContextLoader extends SpringBootContextLoader { - - @Override - protected SpringApplication getSpringApplication() { - return new FunctionalSpringApplication(); - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java deleted file mode 100644 index 375173104..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/GsonMapper.java +++ /dev/null @@ -1,70 +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.json; - -import java.io.Reader; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class GsonMapper extends JsonMapper { - - private final Gson gson; - - public GsonMapper(Gson gson) { - this.gson = gson; - } - - @Override - public String toString(Object value) { - return this.gson.toJson(value); - } - - @Override - protected T doFromJson(Object json, Type type) { - T convertedValue = null; - if (json instanceof byte[]) { - convertedValue = this.gson.fromJson(new String(((byte[]) json), StandardCharsets.UTF_8), type); - } - else if (json instanceof String) { - convertedValue = this.gson.fromJson((String) json, type); - } - else if (json instanceof Reader) { - convertedValue = this.gson.fromJson((Reader) json, type); - } - else if (json instanceof JsonElement) { - convertedValue = this.gson.fromJson((JsonElement) json, type); - } - return convertedValue; - } - - @Override - public byte[] toJson(Object value) { - byte[] jsonBytes = super.toJson(value); - if (jsonBytes == null) { - jsonBytes = this.gson.toJson(value).getBytes(StandardCharsets.UTF_8); - } - return jsonBytes; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java deleted file mode 100644 index fe501485a..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JacksonMapper.java +++ /dev/null @@ -1,96 +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.json; - -import java.io.Reader; -import java.lang.reflect.Type; -import java.util.Map; -import java.util.function.Consumer; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.TypeFactory; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class JacksonMapper extends JsonMapper { - - private final ObjectMapper mapper; - - public JacksonMapper(ObjectMapper mapper) { - this.mapper = mapper; - } - - public void configureObjectMapper(Consumer configurer) { - configurer.accept(mapper); - } - - @Override - protected T doFromJson(Object json, Type type) { - T convertedValue = null; - JavaType constructType = TypeFactory.defaultInstance().constructType(type); - - try { - if (json instanceof String) { - convertedValue = this.mapper.readValue((String) json, constructType); - } - else if (json instanceof byte[]) { - convertedValue = this.mapper.readValue((byte[]) json, constructType); - } - else if (json instanceof Reader) { - convertedValue = this.mapper.readValue((Reader) json, constructType); - } - else if (json instanceof Map) { - convertedValue = this.mapper.convertValue(json, constructType); - } - } - catch (Exception e) { - throw new IllegalStateException("Failed to convert. Possible bug as the conversion probably shouldn't have been attempted here", e); - } - return convertedValue; - } - - @Override - public byte[] toJson(Object value) { - byte[] jsonBytes = super.toJson(value); - if (jsonBytes == null) { - try { - jsonBytes = this.mapper.writeValueAsBytes(value); - } - catch (Exception e) { - //ignore and let other converters have a chance - } - } - return jsonBytes; - } - - @Override - public String toString(Object value) { - try { - return this.mapper.writeValueAsString(value); - } - catch (JsonProcessingException e) { - throw new IllegalArgumentException("Cannot convert to JSON", e); - } - } - - - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java deleted file mode 100644 index 8da030093..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/json/JsonMapper.java +++ /dev/null @@ -1,142 +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.json; - -import java.io.Reader; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public abstract class JsonMapper { - - private static Log logger = LogFactory.getLog(JsonMapper.class); - - @SuppressWarnings("unchecked") - public T fromJson(Object json, Type type) { - if (json instanceof Collection) { - if (FunctionTypeUtils.isTypeCollection(type)) { - return (T) json; - } - Collection inputs = (Collection) json; - Type itemType = FunctionTypeUtils.getImmediateGenericType(type, 0); - Collection results = FunctionTypeUtils.getRawType(type).isAssignableFrom(List.class) - ? new ArrayList<>() - : new HashSet<>(); - for (Object input : inputs) { - results.add(this.doFromJson(input, itemType)); - } - return (T) results; - } - else { - if (!(json instanceof String) && !(json instanceof byte[]) && !(json instanceof Reader)) { - json = this.toJson(json); - if (FunctionTypeUtils.getRawType(type) == String.class) { - return (T) new String((byte[]) json, StandardCharsets.UTF_8); - } - else if (FunctionTypeUtils.getRawType(type) == byte[].class) { - return (T) json; - } - } - if (json instanceof String && (String.class == type || byte[].class == type)) { - return String.class == type ? (T) json : (T) ((String) json).getBytes(StandardCharsets.UTF_8); - } - else { - return this.doFromJson(json, type); - } - } - } - - protected abstract T doFromJson(Object json, Type type); - - public byte[] toJson(Object value) { - byte[] result = null; - if (isJsonString(value)) { - if (logger.isDebugEnabled()) { - logger.debug( - "String already represents JSON. Skipping conversion in favor of 'getBytes(StandardCharsets.UTF_8'."); - } - result = value instanceof byte[] ? (byte[]) value : ((String) value).getBytes(StandardCharsets.UTF_8); - } - else if (value instanceof byte[]) { - result = (byte[]) value; - } - return result; - } - - public abstract String toString(Object value); - - /** - * Performs a simple validation on an object to see if it appears to be a JSON string. - * NOTE: the validation is very rudimentary and simply checks that the object is a String and begins - * and ends with matching pairs of "{}" or "[]" or "\"\"" and therefore may not handle some corner cases. - * Primarily intended for internal of the framework. - * @param value candidate object to evaluate - * @return true if and object appears to be a valid JSON string, otherwise false. - */ - public static boolean isJsonString(Object value) { - boolean isJson = false; - if (value instanceof byte[]) { - value = new String((byte[]) value, StandardCharsets.UTF_8); - } - if (value instanceof String) { - String str = ((String) value).trim(); - isJson = (str.startsWith("\"") && str.endsWith("\"")) || - (str.startsWith("{") && str.endsWith("}")) || - (str.startsWith("[") && str.endsWith("]")); - } - - return isJson; - } - - public static boolean isJsonStringRepresentsCollection(Object value) { - boolean isJson = false; - if (value instanceof Collection && !value.getClass().getPackage().getName().startsWith("reactor.util.function")) { - return true; - } - if (value instanceof byte[]) { - value = new String((byte[]) value, StandardCharsets.UTF_8); - } - if (value instanceof String) { - String str = ((String) value).trim(); - isJson = isJsonString(value) && str.startsWith("[") && str.endsWith("]"); - } - return isJson; - } - - public static boolean isJsonStringRepresentsMap(Object value) { - boolean isJson = false; - if (value instanceof byte[]) { - value = new String((byte[]) value, StandardCharsets.UTF_8); - } - if (value instanceof String) { - String str = ((String) value).trim(); - isJson = isJsonString(value) && str.startsWith("{") && str.endsWith("}"); - } - return isJson; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/DefaultFunctionObservationConvention.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/DefaultFunctionObservationConvention.java deleted file mode 100644 index a31e8719b..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/DefaultFunctionObservationConvention.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013-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.observability; - -import io.micrometer.common.KeyValues; - -/** - * Default implementation of {@link FunctionReceiverObservationConvention}. - * - * @author Marcin Grzejszczak - * @since 4.0.0 - */ -public class DefaultFunctionObservationConvention implements FunctionObservationConvention { - - /** - * Singleton instance of this convention. - */ - public static final FunctionObservationConvention INSTANCE = new DefaultFunctionObservationConvention(); - - @Override - public KeyValues getLowCardinalityKeyValues(FunctionContext context) { - return KeyValues.of(FunctionObservation.FunctionLowCardinalityTags.FUNCTION_NAME.withValue(context.getTargetFunction().getFunctionDefinition())); - } - - @Override - public String getName() { - return "spring.cloud.function"; - } - - @Override - public String getContextualName(FunctionContext context) { - return context.getTargetFunction().getFunctionDefinition() + " process"; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionContext.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionContext.java deleted file mode 100644 index e5bdd89be..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionContext.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2013-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.observability; - -import io.micrometer.observation.Observation; - -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry; -import org.springframework.messaging.Message; - -/** - * {@link Observation.Context} for function processing. - * - * @author Marcin Grzejszczak - * @author Oleg Zhurakousky - * @since 4.0.0 - */ -public class FunctionContext extends Observation.Context { - - private final SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction; - - private final Message message; - - public FunctionContext(SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction, Message message) { - this.targetFunction = targetFunction; - this.message = message; - } - - public SimpleFunctionRegistry.FunctionInvocationWrapper getTargetFunction() { - return targetFunction; - } - -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservation.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservation.java deleted file mode 100644 index a50b38814..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservation.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013-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.observability; - -import io.micrometer.common.docs.KeyName; -import io.micrometer.observation.Observation; -import io.micrometer.observation.ObservationConvention; -import io.micrometer.observation.docs.ObservationDocumentation; - -/** - * @author Marcin Grzejszczak - * @author Oleg Zhurakousky - * @since 4.0.0 - */ -enum FunctionObservation implements ObservationDocumentation { - - /** - * Observation created around processing a message (functional bean processing). - */ - FUNCTION_PROCESSING_OBSERVATION { - @Override - public Class> getDefaultConvention() { - return DefaultFunctionObservationConvention.class; - } - - @Override - public KeyName[] getLowCardinalityKeyNames() { - return FunctionLowCardinalityTags.values(); - } - - @Override - public String getPrefix() { - return "spring.cloud.function"; - } - }; - - enum FunctionLowCardinalityTags implements KeyName { - - /** - * Name of the function. - */ - FUNCTION_NAME { - public String asString() { - return "spring.cloud.function.definition"; - } - } - - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservationConvention.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservationConvention.java deleted file mode 100644 index 1a5be2a0c..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/FunctionObservationConvention.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022-2022 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.observability; - -import io.micrometer.observation.Observation; -import io.micrometer.observation.ObservationConvention; - -/** - * {@link ObservationConvention} for {@link FunctionContext}. - * - * @author Marcin Grzejszczak - * @author Oleg Zhurakousky - * @since 4.0.0 - */ -public interface FunctionObservationConvention extends ObservationConvention { - - @Override - default boolean supportsContext(Observation.Context context) { - return context instanceof FunctionContext; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationAutoConfiguration.java deleted file mode 100644 index ec0e1650f..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationAutoConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022-2022 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.observability; - -import io.micrometer.observation.ObservationRegistry; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.function.context.catalog.FunctionAroundWrapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Oleg Zhurakousky - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnBean(org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration.class) -public class ObservationAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(ObservationRegistry.class) - public FunctionAroundWrapper observationFunctionAroundWrapper(ObservationRegistry registry, - ObjectProvider functionObservationConvention) { - return new ObservationFunctionAroundWrapper(registry, - functionObservationConvention.getIfAvailable(() -> null)); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationFunctionAroundWrapper.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationFunctionAroundWrapper.java deleted file mode 100644 index 8f62c5fa8..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/observability/ObservationFunctionAroundWrapper.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.observability; - -import io.micrometer.observation.Observation; -import io.micrometer.observation.ObservationRegistry; - -import org.springframework.cloud.function.context.catalog.FunctionAroundWrapper; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; - - -/** - * @author Marcin Grzejszczak - * @author Oleg Zhurakousky - * @since 4.0.0 - */ -public class ObservationFunctionAroundWrapper extends FunctionAroundWrapper { - private final ObservationRegistry observationRegistry; - - private final FunctionObservationConvention functionObservationConvention; - - public ObservationFunctionAroundWrapper(ObservationRegistry observationRegistry, @Nullable FunctionObservationConvention functionObservationConvention) { - this.observationRegistry = observationRegistry; - this.functionObservationConvention = functionObservationConvention; - } - - @Override - protected Object doApply(Object message, SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction) { - return nonReactorStream((Message) message, targetFunction); - } - - private Object nonReactorStream(Message message, - SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction) { - return functionProcessingObservation(targetFunction, message).observe(() -> targetFunction.apply(message)); - } - - private Observation functionProcessingObservation(SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction, Message message) { - return FunctionObservation.FUNCTION_PROCESSING_OBSERVATION.observation(this.functionObservationConvention, DefaultFunctionObservationConvention.INSTANCE, () -> new FunctionContext(targetFunction, message), this.observationRegistry); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java deleted file mode 100644 index 1e13b1a33..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionClassUtils.java +++ /dev/null @@ -1,153 +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.utils; - -import java.io.InputStream; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.jar.JarFile; -import java.util.jar.Manifest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.core.KotlinDetector; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -/** - * General utility class which aggregates various class-level utility functions - * used by the framework. - * - * @author Oleg Zhurakousky - * @since 3.0.1 - */ -public final class FunctionClassUtils { - - private static Log logger = LogFactory.getLog(FunctionClassUtils.class); - - private FunctionClassUtils() { - - } - - /** - * Discovers the start class in the currently running application. - * The discover search order is 'MAIN_CLASS' environment property, - * 'MAIN_CLASS' system property, META-INF/MANIFEST.MF:'Start-Class' attribute, - * meta-inf/manifest.mf:'Start-Class' attribute. - * - * @return instance of Class which represent the start class of the application. - */ - public static Class getStartClass() { - ClassLoader classLoader = FunctionClassUtils.class.getClassLoader(); - return getStartClass(classLoader); - } - - static Class getStartClass(ClassLoader classLoader) { - Class mainClass = null; - if (System.getenv("MAIN_CLASS") != null) { - mainClass = ClassUtils.resolveClassName(System.getenv("MAIN_CLASS"), classLoader); - } - else if (System.getProperty("MAIN_CLASS") != null) { - mainClass = ClassUtils.resolveClassName(System.getProperty("MAIN_CLASS"), classLoader); - } - else { - try { - Class result = getStartClass( - Collections.list(classLoader.getResources(JarFile.MANIFEST_NAME)), classLoader); - if (result == null) { - result = getStartClass(Collections - .list(classLoader.getResources("meta-inf/manifest.mf")), classLoader); - } - Assert.notNull(result, "Failed to locate main class"); - mainClass = result; - } - catch (Exception ex) { - throw new IllegalStateException("Failed to discover main class. An attempt was made to discover " - + "main class as 'MAIN_CLASS' environment variable, system property as well as " - + "entry in META-INF/MANIFEST.MF (in that order).", ex); - } - } - logger.info("Main class: " + mainClass); - return mainClass; - } - - private static Class getStartClass(List list, ClassLoader classLoader) { - if (logger.isTraceEnabled()) { - logger.trace("Searching manifests: " + list); - } - for (URL url : list) { - try { - InputStream inputStream = null; - Manifest manifest = new Manifest(url.openStream()); - logger.info("Searching for start class in manifest: " + url); - if (logger.isDebugEnabled()) { - manifest.write(System.out); - } - try { - String startClassName = manifest.getMainAttributes().getValue("Start-Class"); - if (!StringUtils.hasText(startClassName)) { - startClassName = manifest.getMainAttributes().getValue("Main-Class"); - } - - if (StringUtils.hasText(startClassName)) { - Class startClass = ClassUtils.forName(startClassName, classLoader); - - if (KotlinDetector.isKotlinType(startClass)) { - PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver(classLoader); - String packageName = startClass.getPackage().getName(); - Resource[] resources = r.getResources("classpath:" + packageName.replace(".", "/") + "/*.class"); - for (int i = 0; i < resources.length; i++) { - Resource resource = resources[i]; - String className = packageName + "." + (resource.getFilename().replace("/", ".")).replace(".class", ""); - startClass = ClassUtils.forName(className, classLoader); - if (isSpringBootApplication(startClass)) { - logger.info("Loaded Main Kotlin Class: " + startClass); - return startClass; - } - } - } - else if (isSpringBootApplication(startClass)) { - logger.info("Loaded Start Class: " + startClass); - return startClass; - } - } - } - finally { - if (inputStream != null) { - inputStream.close(); - } - } - } - catch (Exception ex) { - logger.debug("Failed to determine Start-Class in manifest file of " + url, ex); - } - } - return null; - } - - private static boolean isSpringBootApplication(Class startClass) { - return startClass.getDeclaredAnnotation(SpringBootApplication.class) != null - || startClass.getDeclaredAnnotation(SpringBootConfiguration.class) != null; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionMessageUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionMessageUtils.java deleted file mode 100644 index 76a6974c0..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/FunctionMessageUtils.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2021-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.utils; - -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; - -/** - * - * !!! INTERNAL ONLY !!! - * - * @author Oleg Zhurakousky - * - */ -public final class FunctionMessageUtils { - - private FunctionMessageUtils() { - - } - - public static String getSourceType(String functionDefinition, Message message) { - return determineSourceFromHeaders(message.getHeaders()); - } - - public static String getTargetType(String functionDefinition, Message message) { - return message.getHeaders().containsKey(MessageUtils.TARGET_PROTOCOL) ? (String) message.getHeaders().get(MessageUtils.TARGET_PROTOCOL) : "unknown"; - } - - private static String determineSourceFromHeaders(MessageHeaders headers) { - for (String key : headers.keySet()) { - if (key.equals(MessageUtils.SOURCE_TYPE)) { - return (String) headers.get(MessageUtils.SOURCE_TYPE); - } - else if (key.startsWith("amqp_")) { - return "amqp"; - } - else if (key.startsWith("kafka_")) { - return "kafka"; - } - else if (key.startsWith("aws_")) { - return "aws"; - } - else if (key.startsWith("solace_")) { - return "solace"; - } - else if (key.toLowerCase().equals("user-agent") || key.toLowerCase().equals("accept-encoding") || key.toLowerCase().equals("host")) { - return "http"; - } - // add rsocket - } - return "origin"; - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/PrimitiveTypesFromStringMessageConverter.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/PrimitiveTypesFromStringMessageConverter.java deleted file mode 100644 index adac52099..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/PrimitiveTypesFromStringMessageConverter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2020-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.utils; - -import java.nio.charset.StandardCharsets; - -import org.springframework.core.convert.ConversionService; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.util.MimeType; - -/** - * - * @author Oleg Zhurakousky - * @since 3.1 - */ -public class PrimitiveTypesFromStringMessageConverter extends AbstractMessageConverter { - - - private final ConversionService conversionService; - - public PrimitiveTypesFromStringMessageConverter(ConversionService conversionService) { - super(new MimeType("text", "plain")); - this.conversionService = conversionService; - } - - - @Override - protected boolean supports(Class clazz) { - return (Integer.class == clazz || Long.class == clazz); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, @Nullable Object conversionHint) { - return conversionService.convert(message.getPayload(), targetClass); - } - - @Override - @Nullable - protected Object convertToInternal(Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - return payload.toString().getBytes(StandardCharsets.UTF_8); - } -} diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/SocketUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/SocketUtils.java deleted file mode 100644 index f83beb913..000000000 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/utils/SocketUtils.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022-2022 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.utils; - -import java.net.ServerSocket; - -public final class SocketUtils { - - private SocketUtils() { - } - - public static int findAvailableTcpPort() { - try { - ServerSocket s = new ServerSocket(0); - int port = s.getLocalPort(); - s.close(); - return port; - } - catch (Exception e) { - // ignore - } - return 0; - } -} diff --git a/spring-cloud-function-context/src/main/kotlin/org/springframework/cloud/function/context/config/CoroutinesUtils.kt b/spring-cloud-function-context/src/main/kotlin/org/springframework/cloud/function/context/config/CoroutinesUtils.kt deleted file mode 100644 index 8614b69db..000000000 --- a/spring-cloud-function-context/src/main/kotlin/org/springframework/cloud/function/context/config/CoroutinesUtils.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2021-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. - */ - -@file:JvmName("CoroutinesUtils") -package org.springframework.cloud.function.context.config - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.reactive.asFlow -import kotlinx.coroutines.reactor.asFlux -import kotlinx.coroutines.reactor.mono -import reactor.core.publisher.Flux -import java.lang.reflect.ParameterizedType -import java.lang.reflect.Type -import java.lang.reflect.WildcardType -import kotlin.coroutines.Continuation -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn - -/** - * @author Adrien Poupard - * - */ - -fun getSuspendingFunctionArgType(type: Type): Type { - return getFlowTypeArguments(type) -} - -fun getFlowTypeArguments(type: Type): Type { - if(!isFlowType(type)) { - return type - } - val parameterizedLowerType = type as ParameterizedType - if(parameterizedLowerType.actualTypeArguments.isEmpty()) { - return parameterizedLowerType - } - - val actualTypeArgument = parameterizedLowerType.actualTypeArguments[0] - return if(actualTypeArgument is WildcardType) { - val wildcardTypeLower = parameterizedLowerType.actualTypeArguments[0] as WildcardType - wildcardTypeLower.upperBounds[0] - } else { - actualTypeArgument - } -} - -fun isFlowType(type: Type): Boolean { - return type.typeName.startsWith(Flow::class.qualifiedName!!) -} - -fun getSuspendingFunctionReturnType(type: Type): Type { - val lower = getContinuationTypeArguments(type) - return getFlowTypeArguments(lower) -} - -fun isContinuationType(type: Type): Boolean { - return type.typeName.startsWith(Continuation::class.qualifiedName!!) -} - -fun isContinuationUnitType(type: Type): Boolean { - return isContinuationType(type) && type.typeName.contains(Unit::class.qualifiedName!!) -} - -fun isContinuationFlowType(type: Type): Boolean { - return isContinuationType(type) && type.typeName.contains(Flow::class.qualifiedName!!) -} - -private fun getContinuationTypeArguments(type: Type): Type { - if(!isContinuationType(type)) { - return type - } - val parameterizedType = type as ParameterizedType - val wildcardType = parameterizedType.actualTypeArguments[0] as WildcardType - return wildcardType.lowerBounds[0] -} - -fun invokeSuspendingFunction(kotlinLambdaTarget: Any, arg0: Any): Flux { - val function = kotlinLambdaTarget as SuspendFunction - val flux = arg0 as Flux - return mono(Dispatchers.Unconfined) { - suspendCoroutineUninterceptedOrReturn> { - function.invoke(flux.asFlow(), it) - } - }.flatMapMany { - it.asFlux() - } -} - -fun invokeSuspendingSupplier(kotlinLambdaTarget: Any): Flux { - val supplier = kotlinLambdaTarget as SuspendSupplier - return mono(Dispatchers.Unconfined) { - suspendCoroutineUninterceptedOrReturn> { - supplier.invoke(it) - } - }.flatMapMany { - it.asFlux() - } -} - -fun invokeSuspendingConsumer(kotlinLambdaTarget: Any, arg0: Any) { - val consumer = kotlinLambdaTarget as SuspendConsumer - val flux = arg0 as Flux - mono(Dispatchers.Unconfined) { - suspendCoroutineUninterceptedOrReturn { - consumer.invoke(flux.asFlow(), it) - } - }.subscribe() -} - -fun isValidSuspendingFunction(kotlinLambdaTarget: Any, arg0: Any): Boolean { - return arg0 is Flux<*> && kotlinLambdaTarget is Function2<*, *, *> -} - -fun isValidSuspendingSupplier(kotlinLambdaTarget: Any): Boolean { - return kotlinLambdaTarget is Function1<*, *> -} - -private typealias SuspendFunction = (Any?, Any?) -> Any? -private typealias SuspendConsumer = (Any?, Any?) -> Unit? -private typealias SuspendSupplier = (Any?) -> Any? diff --git a/spring-cloud-function-context/src/main/resources/META-INF/spring-configuration-metadata.json b/spring-cloud-function-context/src/main/resources/META-INF/spring-configuration-metadata.json deleted file mode 100644 index 18830d28d..000000000 --- a/spring-cloud-function-context/src/main/resources/META-INF/spring-configuration-metadata.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "hints": [], - "groups": [], - "properties": [ - { - "name": "spring.cloud.function.scan.packages", - "type": "java.lang.String", - "description": "Triggers scanning within the specified base packages for any class that is assignable to java.util.function.Function. For each detected Function class, a bean instance will be added to the context.", - "defaultValue": "functions" - }, - { - "name": "spring.cloud.function.definition", - "type": "java.lang.String", - "description": "Name (e.g., 'foo') or composition instruction (e.g., 'foo|bar') used to resolve default function especially for cases where there is more than one function available in catalog.", - "defaultValue": "" - }, - { - "name": "spring.cloud.function.routing.enabled", - "type": "java.lang.Boolean", - "description": "Enables RoutingFunction which delegates incoming request to a function named via function.name header", - "defaultValue": false - } - ] -} diff --git a/spring-cloud-function-context/src/main/resources/META-INF/spring.factories b/spring-cloud-function-context/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 98a7ced06..000000000 --- a/spring-cloud-function-context/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -org.springframework.cloud.function.context.WrapperDetector=\ -org.springframework.cloud.function.context.config.FluxWrapperDetector -org.springframework.context.ApplicationContextInitializer=\ -org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer diff --git a/spring-cloud-function-context/src/main/resources/META-INF/spring/aot.factories b/spring-cloud-function-context/src/main/resources/META-INF/spring/aot.factories deleted file mode 100644 index 750d9d74c..000000000 --- a/spring-cloud-function-context/src/main/resources/META-INF/spring/aot.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=org.springframework.cloud.function.context.FunctionTypeProcessor \ No newline at end of file diff --git a/spring-cloud-function-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 90873e09a..000000000 --- a/spring-cloud-function-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,5 +0,0 @@ -org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration -org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration -org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration -org.springframework.cloud.function.context.config.FunctionsEndpointAutoConfiguration -org.springframework.cloud.function.observability.ObservationAutoConfiguration diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventFunctionTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventFunctionTests.java deleted file mode 100644 index 0ad602b4e..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventFunctionTests.java +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.net.URI; -import java.text.SimpleDateFormat; -import java.util.UUID; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.message.MessageUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; - - - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class CloudEventFunctionTests { - - @SuppressWarnings("unchecked") - @Test - public void testBinaryPojoToPojoDefaultOutputHeaderProvider() { - Function function = this.lookup("echo", TestConfiguration.class); - - String id = UUID.randomUUID().toString(); - - Message inputMessage = CloudEventMessageBuilder - .withData("{\"name\":\"Ricky\"}") - .setId(id) - .setSource("https://spring.io/") - .setType("org.springframework") - .build(); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isTrue(); - - Message resultMessage = (Message) function.apply(inputMessage); - - - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - assertThat(CloudEventMessageUtils.isCloudEvent(resultMessage)).isTrue(); - assertThat(CloudEventMessageUtils.getType(resultMessage)).isEqualTo(Person.class.getName()); - assertThat(CloudEventMessageUtils.getSource(resultMessage)).isEqualTo(URI.create("http://spring.io/")); - } - - /* - * Aside from the properly processing and recognizing CE, the following tow tests (imperative and reactive) - * also emulate message coming from one protocol going to another via MessageUtils.TARGET_PROTOCOL header that - * is set here explicitly but for instance in s-c-stream is set by the framework - */ - @Test - public void testBinaryPojoToPojoDefaultOutputHeaderProviderImperative() { - Function function = this.lookup("springRelease", TestConfiguration.class); - - String id = UUID.randomUUID().toString(); - - String payload = "{\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }"; - - Message inputMessage = CloudEventMessageBuilder - .withData(payload) - .setId(id) - .setSource("https://spring.io/") - .setType("org.springframework") - .setHeader(MessageUtils.TARGET_PROTOCOL, CloudEventMessageUtils.Protocols.KAFKA) - .build(CloudEventMessageUtils.AMQP_ATTR_PREFIX); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isTrue(); - - Message message = (Message) function.apply(inputMessage); - - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - - assertThat(CloudEventMessageUtils.isCloudEvent(message)).isTrue(); - assertThat(CloudEventMessageUtils.getType(message)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(message)).isEqualTo(URI.create("http://spring.io/")); - assertThat(message.getHeaders().get("ce_source")).isEqualTo(URI.create("http://spring.io/")); - } - - @SuppressWarnings("unchecked") - @Test - public void testBinaryPojoToPojoDefaultOutputHeaderProviderReactive() { - Function function = this.lookup("springReleaseReactive", TestConfiguration.class); - - String id = UUID.randomUUID().toString(); - - String payload = "{\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }"; - - Message inputMessage = CloudEventMessageBuilder - .withData(payload) - .setId(id) - .setSource("https://spring.io/") - .setType("org.springframework") - .setHeader(MessageUtils.TARGET_PROTOCOL, CloudEventMessageUtils.Protocols.KAFKA) - .build(CloudEventMessageUtils.AMQP_ATTR_PREFIX); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isTrue(); - - Message message = ((Flux>) function.apply(Flux.just(inputMessage))).blockFirst(); - - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - - assertThat(CloudEventMessageUtils.isCloudEvent(message)).isTrue(); - assertThat(CloudEventMessageUtils.getType(message)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(message)).isEqualTo(URI.create("http://spring.io/")); - assertThat(message.getHeaders().get("ce_source")).isEqualTo(URI.create("http://spring.io/")); - } - - @SuppressWarnings("unchecked") - @Test - public void testBinaryPojoToPojoDefaultOutputHeaderProviderReactiveMono() { - Function function = this.lookup("springReleaseReactiveMono", TestConfiguration.class); - - String id = UUID.randomUUID().toString(); - - String payload = "{\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }"; - - Message inputMessage = CloudEventMessageBuilder - .withData(payload) - .setId(id) - .setSource("https://spring.io/") - .setType("org.springframework") - .setHeader(MessageUtils.TARGET_PROTOCOL, CloudEventMessageUtils.Protocols.KAFKA) - .build(CloudEventMessageUtils.AMQP_ATTR_PREFIX); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isTrue(); - - Message message = ((Mono>) function.apply(Mono.just(inputMessage))).block(); - - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - - assertThat(CloudEventMessageUtils.isCloudEvent(message)).isTrue(); - assertThat(CloudEventMessageUtils.getType(message)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(message)).isEqualTo(URI.create("http://spring.io/")); - assertThat(message.getHeaders().get("ce_source")).isEqualTo(URI.create("http://spring.io/")); - } - - - // this kind of emulates that message came from Kafka - @SuppressWarnings("unchecked") - @Test - public void testBinaryPojoToPojoDefaultOutputHeaderProviderWithPrefix() { - Function function = this.lookup("echo", TestConfiguration.class); - - String id = UUID.randomUUID().toString(); - - Message inputMessage = CloudEventMessageBuilder - .withData("{\"name\":\"Ricky\"}") - .setHeader("ce_id", id) - .setHeader("ce_source", "https://spring.io/") - .setHeader("ce_type", "org.springframework") - .build(); - - Message resultMessage = (Message) function.apply(inputMessage); - - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - assertThat(CloudEventMessageUtils.isCloudEvent(resultMessage)).isTrue(); - assertThat(CloudEventMessageUtils.getType(resultMessage)).isEqualTo(Person.class.getName()); - assertThat(CloudEventMessageUtils.getSource(resultMessage)).isEqualTo(URI.create("http://spring.io/")); - } - - @SuppressWarnings("unchecked") - @Test - public void testStructuredPojoToPojoDefaultOutputAttributeProvider() throws Exception { - String payload = "{\n" + - " \"specversion\" : \"1.0\",\n" + - " \"type\" : \"org.springframework\",\n" + - " \"source\" : \"https://spring.io/\",\n" + - " \"id\" : \"A234-1234-1234\",\n" + - " \"datacontenttype\" : \"application/json\",\n" + - " \"data\" : {\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }\n" + - "}"; - Function function = this.lookup("springRelease", TestConfiguration.class); - - Message inputMessage = MessageBuilder - .withPayload(payload) - .setHeader(MessageHeaders.CONTENT_TYPE, CloudEventMessageUtils.APPLICATION_CLOUDEVENTS_VALUE + "+json") - .build(); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isFalse(); - - Message resultMessage = (Message) function.apply(inputMessage); - assertThat(resultMessage.getPayload().getReleaseDate()) - .isEqualTo(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - assertThat(resultMessage.getPayload().getVersion()).isEqualTo("2.0"); -// /* -// * Validates that although user only deals with POJO, the framework recognizes -// * both on input and output that it is dealing with Cloud Event and generates -// * appropriate headers/attributes -// */ - assertThat(CloudEventMessageUtils.isCloudEvent(resultMessage)).isTrue(); - assertThat(CloudEventMessageUtils.getType(resultMessage)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(resultMessage)).isEqualTo(URI.create("http://spring.io/")); - } - - @SuppressWarnings("unchecked") - @Test - public void testStructuredPojoToPojoMessageFunction() throws Exception { - String payload = "{\n" + - " \"specversion\" : \"1.0\",\n" + - " \"type\" : \"org.springframework\",\n" + - " \"source\" : \"https://spring.io/\",\n" + - " \"id\" : \"A234-1234-1234\",\n" + - " \"datacontenttype\" : \"application/json\",\n" + - " \"data\" : {\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }\n" + - "}"; - Function function = this.lookup("springReleaseAsMessage", TestConfiguration.class); - - Message inputMessage = MessageBuilder - .withPayload(payload) - .setHeader(MessageHeaders.CONTENT_TYPE, CloudEventMessageUtils.APPLICATION_CLOUDEVENTS_VALUE + "+json") - .build(); - - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isFalse(); - - Message resultMessage = (Message) function.apply(inputMessage); - assertThat(resultMessage.getPayload().getReleaseDate()) - .isEqualTo(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - assertThat(resultMessage.getPayload().getVersion()).isEqualTo("2.0"); -// /* -// * Validates that although user only deals with POJO, the framework recognizes -// * both on input and output that it is dealing with Cloud Event and generates -// * appropriate headers/attributes -// */ - assertThat(CloudEventMessageUtils.isCloudEvent(resultMessage)).isTrue(); - assertThat(CloudEventMessageUtils.getType(resultMessage)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(resultMessage)).isEqualTo(URI.create("https://spring.release.event")); - } - - @SuppressWarnings("unchecked") - @Test - public void testStructuredPojoToPojoDefaultOutputAttributeProviderNoDataContentType() throws Exception { - String payload = "{\n" + - " \"ce_specversion\" : \"1.0\",\n" + - " \"ce_type\" : \"org.springframework\",\n" + - " \"ce_source\" : \"https://spring.io/\",\n" + - " \"ce_id\" : \"A234-1234-1234\",\n" + - " \"ce_data\" : {\n" + - " \"version\" : \"1.0\",\n" + - " \"releaseName\" : \"Spring Framework\",\n" + - " \"releaseDate\" : \"24-03-2004\"\n" + - " }\n" + - "}"; - Function function = this.lookup("springRelease", TestConfiguration.class); - - Message inputMessage = MessageBuilder - .withPayload(payload) - .setHeader(MessageHeaders.CONTENT_TYPE, CloudEventMessageUtils.APPLICATION_CLOUDEVENTS_VALUE + "+json") - .build(); - assertThat(CloudEventMessageUtils.isCloudEvent(inputMessage)).isFalse(); - - Message resultMessage = (Message) function.apply(inputMessage); - assertThat(resultMessage.getPayload().getReleaseDate()) - .isEqualTo(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - assertThat(resultMessage.getPayload().getVersion()).isEqualTo("2.0"); - /* - * Validates that although user only deals with POJO, the framework recognizes - * both on input and output that it is dealing with Cloud Event and generates - * appropriate headers/attributes - */ - assertThat(CloudEventMessageUtils.isCloudEvent(resultMessage)).isTrue(); - assertThat(CloudEventMessageUtils.getType(resultMessage)).isEqualTo(SpringReleaseEvent.class.getName()); - assertThat(CloudEventMessageUtils.getSource(resultMessage)).isEqualTo(URI.create("http://spring.io/")); - } - - private Function lookup(String functionDefinition, Class... configClass) { - ApplicationContext context = new SpringApplicationBuilder(configClass).run( - "--logging.level.org.springframework.cloud.function=DEBUG", "--spring.main.lazy-initialization=true"); - return context.getBean(FunctionCatalog.class).lookup(functionDefinition); - } - - @EnableAutoConfiguration - @Configuration - public static class TestConfiguration { - @Bean - Function echo() { - return Function.identity(); - } - - @Bean - Function springRelease() { - return event -> { - try { - event.setReleaseDate(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - event.setVersion("2.0"); - return event; - } - catch (Exception e) { - throw new IllegalArgumentException(e); - } - }; - } - - @Bean - Function, Flux> springReleaseReactive() { - return flux -> flux.map(event -> { - try { - event.setReleaseDate(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - event.setVersion("2.0"); - return event; - } - catch (Exception e) { - throw new IllegalArgumentException(e); - } - }); - } - - @Bean - Function, Mono> springReleaseReactiveMono() { - return mono -> mono.map(event -> { - try { - event.setReleaseDate(new SimpleDateFormat("dd-MM-yyyy").parse("01-10-2006")); - event.setVersion("2.0"); - return event; - } - catch (Exception e) { - throw new IllegalArgumentException(e); - } - }); - } - - @Bean - Function, Message> springReleaseAsMessage() { - return message -> { - SpringReleaseEvent updated = springRelease().apply(message.getPayload()); - assertThat(message.getHeaders().get("ce-type")).isEqualTo("org.springframework"); - return CloudEventMessageBuilder.withData(updated) - .copyHeaders(message.getHeaders()) - .setSource("https://spring.release.event") - .setType(SpringReleaseEvent.class.getName()) - .build(); - }; - } - } - - public static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtilsAndBuilderTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtilsAndBuilderTests.java deleted file mode 100644 index 0161f6367..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/CloudEventMessageUtilsAndBuilderTests.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.net.URI; -import java.util.Map; - -import org.junit.jupiter.api.Test; - -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - */ -public class CloudEventMessageUtilsAndBuilderTests { - - @Test// see https://github.com/spring-cloud/spring-cloud-function/issues/805 - public void testHeaderKeyInsensitivity() { - Message httpMessage = MessageBuilder.withPayload("hello") - .setHeader("cE-SoUrCe", "https://foo.bar") - .setHeader("Ce-specVeRsion", "1.0") - .setHeader("Ce-Type", "blah") - .setHeader("x", "x") - .setHeader("zzz", "zzz") - .build(); - - assertThat(CloudEventMessageUtils.isCloudEvent(httpMessage)).isTrue(); - } - - @Test// see https://github.com/spring-cloud/spring-cloud-function/issues/680 - public void testProperAttributeExtractionRegardlessOfTargetProtocol() { - Message ceMessage = CloudEventMessageBuilder.withData("foo").build(); - ceMessage = MessageBuilder.fromMessage(ceMessage).setHeader("target-protocol", "kafka").build(); - - String prefix = CloudEventMessageUtils.determinePrefixToUse(ceMessage.getHeaders()); - assertThat(prefix).isEqualTo("ce-"); - prefix = CloudEventMessageUtils.determinePrefixToUse(ceMessage.getHeaders(), true); - assertThat(prefix).isEqualTo("ce_"); - - String specVersion = CloudEventMessageUtils.getSpecVersion(ceMessage); - assertThat(specVersion).isEqualTo("1.0"); - String type = CloudEventMessageUtils.getType(ceMessage); - assertThat(type).isEqualTo("java.lang.String"); - String id = CloudEventMessageUtils.getId(ceMessage); - assertThat(id).isNotNull(); - URI source = CloudEventMessageUtils.getSource(ceMessage); - assertThat(source.toString()).isEqualTo("https://spring.io/"); - } - - @Test - public void testAttributeRecognitionAndCanonicalization() { - Message httpMessage = MessageBuilder.withPayload("hello") - .setHeader(CloudEventMessageUtils.SOURCE, "https://foo.bar") - .setHeader(CloudEventMessageUtils.SPECVERSION, "1.0") - .setHeader(CloudEventMessageUtils.TYPE, "blah") - .setHeader("x", "x") - .setHeader("zzz", "zzz") - .build(); - Map attributes = CloudEventMessageUtils.getAttributes(httpMessage); - assertThat(attributes.size()).isEqualTo(3); - assertThat((String) CloudEventMessageUtils.getData(httpMessage)).isEqualTo("hello"); - - Message kafkaMessage = CloudEventMessageBuilder.fromMessage(httpMessage).build(CloudEventMessageUtils.KAFKA_ATTR_PREFIX); - attributes = CloudEventMessageUtils.getAttributes(kafkaMessage); - assertThat(attributes.size()).isEqualTo(4); // id will be auto injected, so always at least 4 (as tehre are 4 required attributes in CE) - assertThat(kafkaMessage.getHeaders().get("ce_source")).isNotNull(); - assertThat(CloudEventMessageUtils.getSource(kafkaMessage)).isEqualTo(URI.create("https://foo.bar")); - assertThat(kafkaMessage.getHeaders().get("ce_type")).isNotNull(); - assertThat(CloudEventMessageUtils.getType(kafkaMessage)).isEqualTo("blah"); - assertThat(kafkaMessage.getHeaders().get("ce_specversion")).isNotNull(); - assertThat(CloudEventMessageUtils.getSpecVersion(kafkaMessage)).isEqualTo("1.0"); - - httpMessage = CloudEventMessageBuilder.fromMessage(kafkaMessage).build(CloudEventMessageUtils.DEFAULT_ATTR_PREFIX); - attributes = CloudEventMessageUtils.getAttributes(httpMessage); - assertThat(attributes.size()).isEqualTo(4); // - assertThat(httpMessage.getHeaders().get("ce-source")).isNotNull(); - assertThat(CloudEventMessageUtils.getSource(httpMessage)).isEqualTo(URI.create("https://foo.bar")); - assertThat(httpMessage.getHeaders().get("ce-type")).isNotNull(); - assertThat(CloudEventMessageUtils.getType(httpMessage)).isEqualTo("blah"); - assertThat(httpMessage.getHeaders().get("ce-specversion")).isNotNull(); - assertThat(CloudEventMessageUtils.getSpecVersion(httpMessage)).isEqualTo("1.0"); - } - - @Test - void canonicalizeHeadersWithPossibleCopyReturnsCopyWithUpdatedHeadersWhenModified() { - // TODO add the following test cases - // - // defaultAttrs w/ unmodified keys -> not modified - // defaultAttrs w/ modified keys -> modified - // kafkaAttrs w/ (defaultAttrs+unmodified keys) -> modified - // amqpAttrs -> modified - // structured -> modified - Message inputMessage = MessageBuilder.withPayload("hello") - .setHeader("ce_foo", "bar") - .setHeader("x", "x1") - .setHeader("x|x", "x2") - .build(); - - Message updatedMessage = CloudEventMessageUtils.canonicalizeHeadersWithPossibleCopy(inputMessage); - - assertThat(inputMessage).isNotSameAs(updatedMessage); - assertThat(updatedMessage.getHeaders()) - .containsEntry("ce-foo", "bar") - .containsEntry("x", "x1") - .containsEntry("x|x", "x2"); - } - - @Test - void canonicalizeHeadersWithPossibleCopyReturnsSameInstanceWhenNotModified() { - Message inputMessage = MessageBuilder.withPayload("hello") - .setHeader("ce-foo", "bar") - .setHeader("x", "x1") - .setHeader("x|x", "x2") - .build(); - - Message updatedMessage = CloudEventMessageUtils.canonicalizeHeadersWithPossibleCopy(inputMessage); - - assertThat(inputMessage).isSameAs(updatedMessage); - assertThat(updatedMessage.getHeaders()) - .containsEntry("ce-foo", "bar") - .containsEntry("x", "x1") - .containsEntry("x|x", "x2"); - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java deleted file mode 100644 index 5afe8953f..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/cloudevent/SpringReleaseEvent.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020-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.cloudevent; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.fasterxml.jackson.annotation.JsonFormat; - -/** - * An example POJO that represents cloud event data. - * - * @author Oleg Zhurakousky - * - */ -public class SpringReleaseEvent { - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") - private Date releaseDate; - - private String releaseName; - - private String version; - - public Date getReleaseDate() { - return releaseDate; - } - - public void setReleaseDate(Date releaseDate) { - this.releaseDate = releaseDate; - } - - public String getReleaseName() { - return releaseName; - } - - public void setReleaseName(String releaseName) { - this.releaseName = releaseName; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @Override - public String toString() { - return "releaseDate:" + new SimpleDateFormat("dd-MM-yyyy").format(releaseDate) + "; releaseName:" + releaseName + "; version:" + version; - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HeaderMappingTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HeaderMappingTests.java deleted file mode 100644 index 67c3506e9..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HeaderMappingTests.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2021-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.context; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -//NOTE!!! assertions for input in all tests are in 'echo' function since we're validating what's coming into it. -public class HeaderMappingTests { - - @Test - public void testErrorWarnAndContinue() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echoFail.input-header-mapping-expression[0].key1=hello1", - "--spring.cloud.function.configuration.echoFail.input-header-mapping-expression[0].key2='hello2'", - "--spring.cloud.function.configuration.echoFail.input-header-mapping-expression[0].foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echoFail"); - function.apply(MessageBuilder.withPayload("helo").build()); - } - } - - @Test - public void testInputHeaderMappingPropertyWithIndex() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1='hello1'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key2='hello2'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - } - } - - @Test - public void testInputHeaderMappingPropertyWithIndexMix() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key1='hello1'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key2='hello2'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - } - } - - @Test - public void testInputHeaderMappingPropertyWithIndexMixDeux() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key1='hello1'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression[0].key2='hello2'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - } - } - - @Test - public void testInputHeaderMappingPropertyWithoutIndex() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key1='hello1'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.key2='hello2'", - "--spring.cloud.function.configuration.echo.input-header-mapping-expression.foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - } - } - - @Test - public void testInputHeaderMappingExpressionWithCompositionWithIndex() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key1='hello1'", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].key2='hello2'", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression[0].foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo|foo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - } - } - - @Test - public void testInputHeaderMappingExpressionWithCompositionWithoutIndex() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key1='hello1'", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.key2='hello2'", - "--spring.cloud.function.configuration.echofoo.input-header-mapping-expression.foo=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("echo|foo"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - - //assertions are in 'echo' function since we're validating what's coming into it. - } - } - - @Test - public void testInputHeaderMappingPropertyWithSplitExpression() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key1=headers.path.split('/')[0]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key2=headers.path.split('/')[1]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key3=headers.path")) { - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("split"); - function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setHeader("path", "foo/bar/baz").build()); - } - } - - @SuppressWarnings("unchecked") - @Test - public void testOutputHeaderMapping() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.foo.output-header-mapping-expression.keyOut1='hello1'", - "--spring.cloud.function.configuration.foo.output-header-mapping-expression.keyOut2=headers.contentType")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("foo"); - Message result = (Message) function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - assertThat(result.getHeaders().containsKey("keyOut1")).isTrue(); - assertThat(result.getHeaders().get("keyOut1")).isEqualTo("hello1"); - assertThat(result.getHeaders().containsKey("keyOut2")).isTrue(); - assertThat(result.getHeaders().get("keyOut2")).isEqualTo("application/json"); - } - } - - @SuppressWarnings("unchecked") - @Test - public void testMixedInputOutputHeaderMapping() throws Exception { - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - SampleFunctionConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut1='hello1'", - "--spring.cloud.function.configuration.split.output-header-mapping-expression.keyOut2=headers.contentType", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key1=headers.path.split('/')[0]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key2=headers.path.split('/')[1]", - "--spring.cloud.function.configuration.split.input-header-mapping-expression.key3=headers.path")) { - - FunctionCatalog functionCatalog = context.getBean(FunctionCatalog.class); - FunctionInvocationWrapper function = functionCatalog.lookup("split"); - Message result = (Message) function.apply(MessageBuilder.withPayload("helo") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setHeader("path", "foo/bar/baz").build()); - assertThat(result.getHeaders().containsKey("keyOut1")).isTrue(); - assertThat(result.getHeaders().get("keyOut1")).isEqualTo("hello1"); - assertThat(result.getHeaders().containsKey("keyOut2")).isTrue(); - assertThat(result.getHeaders().get("keyOut2")).isEqualTo("application/json"); - } - } - - @EnableAutoConfiguration - @Configuration - protected static class SampleFunctionConfiguration { - - @Bean - public Function, Message> echo() { - return m -> { - assertThat(m.getHeaders().get("key1")).isEqualTo("hello1"); - assertThat(m.getHeaders().get("key2")).isEqualTo("hello2"); - assertThat(m.getHeaders().get("foo")).isEqualTo("application/json"); - return m; - }; - } - - @Bean - public Function, Message> echoFail() { - return m -> { - assertThat(m.getHeaders().containsKey("key1")).isFalse(); - assertThat(m.getHeaders().get("key2")).isEqualTo("hello2"); - assertThat(m.getHeaders().containsKey("foo")).isFalse(); - return m; - }; - } - - @Bean - public Function, Message> split() { - return m -> { - assertThat(m.getHeaders().get("key1")).isEqualTo("foo"); - assertThat(m.getHeaders().get("key2")).isEqualTo("bar"); - assertThat(m.getHeaders().get("key3")).isEqualTo("foo/bar/baz"); - return m; - }; - } - - @Bean - public Function, Message> foo() { - return x -> { - assertThat(x.getHeaders().containsKey("keyOut1")).isFalse(); - return x; - }; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HybridFunctionalRegistrationTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HybridFunctionalRegistrationTests.java deleted file mode 100644 index fd8b3d843..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/HybridFunctionalRegistrationTests.java +++ /dev/null @@ -1,126 +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.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class HybridFunctionalRegistrationTests { - - // see https://github.com/spring-cloud/spring-cloud-function/issues/258 - @SuppressWarnings("rawtypes") - @Test - public void testNoDoubleRegistrationInHybridMode() { - ConfigurableApplicationContext context = FunctionalSpringApplication - .run(UppercaseFunction.class, "--spring.functional.enabled=false"); - - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - assertThat(context.containsBean("function")).isTrue(); - assertThat(context.getBeansOfType(UppercaseFunction.class).size()).isEqualTo(1); - assertThat((Function) catalog.lookup("hybridFunctionalRegistrationTests.UppercaseFunction")).isNotNull(); - } - - @SuppressWarnings("rawtypes") - @Test - public void testMessageHeaderPropagationInFunctionalBeanRegistration() { - ConfigurableApplicationContext context = FunctionalSpringApplication - .run(UppercaseMessageFunction.class, "--spring.functional.enabled=false"); - - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - assertThat(context.containsBean("function")).isTrue(); - assertThat(context.getBeansOfType(UppercaseMessageFunction.class).size()).isEqualTo(1); - Function f = catalog.lookup(Function.class, "hybridFunctionalRegistrationTests.UppercaseMessageFunction"); - assertThat(f).isNotNull(); - String result = (String) f.apply(MessageBuilder.withPayload("hello").setHeader("foo", "foo").setHeader("blah", "blah").build()); - assertThat(result).isEqualTo("HELLO"); - } - - @SuppressWarnings("rawtypes") - @Test - public void testNoDoubleRegistrationInHybridModeFluxedFunction() { - ConfigurableApplicationContext context = FunctionalSpringApplication - .run(UppercaseFluxFunction.class, "--spring.functional.enabled=false"); - - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - assertThat(context.containsBean("function")).isTrue(); - assertThat(context.getBeansOfType(UppercaseFluxFunction.class).size()).isEqualTo(1); - assertThat((Function) catalog.lookup(Function.class, "hybridFunctionalRegistrationTests.UppercaseFluxFunction")).isNotNull(); - } - - @SpringBootConfiguration - @ImportAutoConfiguration({ - ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class } - ) - public static class UppercaseFunction implements Function { - - @Override - public String apply(String t) { - return t.toUpperCase(); - } - } - - @SpringBootConfiguration - @ImportAutoConfiguration({ - ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class } - ) - public static class UppercaseMessageFunction implements Function, String> { - - @Override - public String apply(Message message) { - assertThat(message.getHeaders().get("foo")).isEqualTo("foo"); - assertThat(message.getHeaders().get("blah")).isEqualTo("blah"); - return message.getPayload().toUpperCase(); - } - } - - @SpringBootConfiguration - @ImportAutoConfiguration({ - ContextFunctionCatalogAutoConfiguration.class, - JacksonAutoConfiguration.class } - ) - public static class UppercaseFluxFunction implements Function, Flux> { - - @Override - public Flux apply(Flux flux) { - return flux.map(v -> v.toUpperCase()); - } - - - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/MessageRoutingCallbackTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/MessageRoutingCallbackTests.java deleted file mode 100644 index 11dfc1daf..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/MessageRoutingCallbackTests.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2021-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.context; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.function.Function; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -public class MessageRoutingCallbackTests { - - private ApplicationContext context; - - @BeforeEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - } - - @SuppressWarnings("unchecked") - @Test - public void testRoutingCallbackWithMessageModification() { - FunctionCatalog catalog = this.configureCatalog(SamppleConfiguration.class); - SamppleConfiguration conf = context.getBean(SamppleConfiguration.class); - FunctionInvocationWrapper function = (FunctionInvocationWrapper) catalog.lookup(RoutingFunction.FUNCTION_NAME, "application/json"); - String foo = "{\"foo\":\"blah\"}"; - Message fooResult = (Message) function.apply(MessageBuilder.withPayload(foo.getBytes()).build()); - String bar = "{\"bar\":\"blah\"}"; - Message barResult = (Message) function.apply(MessageBuilder.withPayload(bar.getBytes()).build()); - assertThat(fooResult.getPayload()).isEqualTo("\"foo\"".getBytes()); - assertThat(barResult.getPayload()).isEqualTo("\"bar\"".getBytes()); - - assertThat(fooResult.getHeaders().get("originalId")).isEqualTo(conf.createdMessageIds.get("foo")); - assertThat(barResult.getHeaders().get("originalId")).isEqualTo(conf.createdMessageIds.get("bar")); - } - - private FunctionCatalog configureCatalog(Class... configClass) { - this.context = new SpringApplicationBuilder(configClass) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - @EnableAutoConfiguration - private static class SamppleConfiguration { - - Map createdMessageIds = new HashMap<>(); - - @Bean - public MessageRoutingCallback messageRoutingCallback(JsonMapper jsonMapper) { - return new MessageRoutingCallback() { - - @Override - public String routingResult(Message message) { - String payload = new String((byte[]) message.getPayload()); - - MessageBuilder builder; - String functionDefinition; - if (payload.contains("foo")) { - builder = MessageBuilder.withPayload(jsonMapper.fromJson(payload, Foo.class)); - functionDefinition = "foo"; - } - else { - builder = MessageBuilder.withPayload(jsonMapper.fromJson(payload, Bar.class)); - functionDefinition = "bar"; - } - Message m = builder.copyHeaders(message.getHeaders()).build(); - createdMessageIds.put(functionDefinition, m.getHeaders().getId()); - return functionDefinition; - } - }; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - public Function, Message> foo() { - return foo -> { - Message m = MessageBuilder.withPayload("foo").setHeader("originalId", foo.getHeaders().getId()).build(); - createdMessageIds.put("foo", foo.getHeaders().getId()); - return m; - }; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - public Function, Message> bar() { - return bar -> { - Message m = MessageBuilder.withPayload("bar").setHeader("originalId", bar.getHeaders().getId()).build(); - createdMessageIds.put("bar", bar.getHeaders().getId()); - return m; - }; - } - } - - - public static class Foo { - private String foo; - - public String getFoo() { - return foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - } - - public static class Bar { - private String bar; - - public String getBar() { - return bar; - } - - public void setBar(String bar) { - this.bar = bar; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryMultiInOutTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryMultiInOutTests.java deleted file mode 100644 index 4039e1cd2..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryMultiInOutTests.java +++ /dev/null @@ -1,487 +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.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Function; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuple3; -import reactor.util.function.Tuples; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class BeanFactoryAwareFunctionRegistryMultiInOutTests { - - private FunctionCatalog configureCatalog() { - ApplicationContext context = new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - /* - * This test validates , Flux> without any type conversion - */ - @Test - public void testMultiInput() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("multiInputSingleOutputViaReactiveTuple"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just(1, 2, 3); - - List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); - assertThat(result.get(0).equals("one-1")); - assertThat(result.get(1).equals("one-2")); - assertThat(result.get(2).equals("one-3")); - } - - @Test - public void testMultiInputWithPojoConversion() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("thomas", "application/json"); - CartEvent carEvent = new CartEvent(); - carEvent.setCarEvent("carEvent"); - Flux carEventStream = Flux.just(carEvent); - - CheckoutEvent checkoutEvent = new CheckoutEvent(); - checkoutEvent.setCheckoutEvent("checkoutEvent"); - Flux checkoutEventStream = Flux.just(checkoutEvent); - - Tuple2, Flux> streams = Tuples.of(carEventStream, checkoutEventStream); - - List result = multiInputFunction.apply(streams).collectList().block(); - System.out.println(result); - } - - @SuppressWarnings("unused") - @Test - @Disabled - public void testMultiInputBiFunction() { - FunctionCatalog catalog = this.configureCatalog(); - BiFunction, Flux, Flux> multiInputFunction = - catalog.lookup(BiFunction.class, "multiInputSingleOutputViaBiFunction"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just(1, 2, 3); - -// List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); -// System.out.println(result); - } - - /* - * This test invokes the same function as above but with types reversed. - * While the target function remains , Flux> - * it is actually invoked as Tuple2, Flux> - * hence showcasing type conversion using Spring's ConversionService - */ - @Test - public void testMultiInputWithConversion() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("multiInputSingleOutputViaReactiveTuple"); - Flux stringStream = Flux.just(11, 22, 33); - Flux intStream = Flux.just("1", "2", "2"); - - List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); - assertThat(result.get(0).equals("11-1")); - assertThat(result.get(1).equals("22-2")); - assertThat(result.get(2).equals("33-3")); - } - - /* - * Same as above but with composing 'uppercase' function essentially validating \ - * composition in multi-input scenario - */ - @Test - @Disabled - public void testMultiInputWithComposition() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("multiInputSingleOutputViaReactiveTuple|uppercase"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just("1", "2", "3"); - - List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); - System.out.println(result); - } - - /* - * This is basically the repeater function currently prototyped in Riff - * The only difference it uses Tuple2 instead of BiFunction (which we will support anyway) - */ - @Test - public void testMultiOutputAsArray() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux[]> repeater = - catalog.lookup("repeater"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just(3, 2, 1); - - Flux[] result = repeater.apply(Tuples.of(stringStream, intStream)); - result[0].subscribe(System.out::println); - result[1].subscribe(System.out::println); - } - - - /* - * This test demonstrates single input into multiple outputs - * as Tuple3 thus making output types known. - * - * The input is a POJO (Person) - * no conversion - */ - @Test - public void testMultiOutputAsTuplePojoInInputTypeMatch() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Tuple3, Flux, Flux>> multiOutputFunction = - catalog.lookup("multiOutputAsTuplePojoIn"); - Flux personStream = Flux.just(new Person("Uncle Sam", 1), new Person("Oncle Pierre", 2)); - - Tuple3, Flux, Flux> result = multiOutputFunction.apply(personStream); - result.getT1().subscribe(v -> System.out.println("=> 1: " + v)); - result.getT2().subscribe(v -> System.out.println("=> 2: " + v)); - result.getT3().subscribe(v -> System.out.println("=> 3: " + v)); - } - - /* - * This test is identical to the previous one with the exception that the - * input is a Message with payload as JSON byte array representation of Person (expected by the target function), - * thus demonstrating Message Conversion - */ - @Test - public void testMultiOutputAsTuplePojoInInputByteArray() { - FunctionCatalog catalog = this.configureCatalog(); - Function>, Tuple3, Flux, Flux>> multiOutputFunction = - catalog.lookup("multiOutputAsTuplePojoIn"); - - Message uncleSam = MessageBuilder.withPayload("{\"name\":\"Uncle Sam\",\"id\":1}".getBytes(StandardCharsets.UTF_8)) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - Message unclePierre = MessageBuilder.withPayload("{\"name\":\"Oncle Pierre\",\"id\":2}".getBytes(StandardCharsets.UTF_8)) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - Flux> personStream = Flux.just(uncleSam, unclePierre); - - Tuple3, Flux, Flux> result = multiOutputFunction.apply(personStream); - result.getT1().subscribe(v -> System.out.println("=> 1: " + v)); - result.getT2().subscribe(v -> System.out.println("=> 2: " + v)); - result.getT3().subscribe(v -> System.out.println("=> 3: " + v)); - } - - /* - * This is another variation of the above. In this case the signature of the target function is - * >, Tuple3, Flux, Flux>> yet we are sending - * Message with payload as byte[] which is converted to Person and then embedded in new Message - * passed to a function - */ - @Test - public void testMultiOutputAsTuplePojoInInputByteArrayInputTypePojoMessage() { - FunctionCatalog catalog = this.configureCatalog(); - Function>, Tuple3, Flux, Flux>> multiOutputFunction = - catalog.lookup("multiOutputAsTupleMessageIn"); - - Message uncleSam = MessageBuilder.withPayload("{\"name\":\"Uncle Sam\",\"id\":1}".getBytes(StandardCharsets.UTF_8)) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - Message unclePierre = MessageBuilder.withPayload("{\"name\":\"Oncle Pierre\",\"id\":2}".getBytes(StandardCharsets.UTF_8)) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - Flux> personStream = Flux.just(uncleSam, unclePierre); - - Tuple3, Flux, Flux> result = multiOutputFunction.apply(personStream); - result.getT1().subscribe(v -> System.out.println("=> 1: " + v)); - result.getT2().subscribe(v -> System.out.println("=> 2: " + v)); - result.getT3().subscribe(v -> System.out.println("=> 3: " + v)); - } - - @Test - public void testMultiToMulti() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux, Flux>, Tuple2, Mono>> multiToMulti = - catalog.lookup("multiToMulti"); - - Flux firstFlux = Flux.just("Unlce", "Oncle"); - Flux secondFlux = Flux.just("Sam", "Pierre"); - Flux thirdFlux = Flux.just(1, 2); - - Tuple2, Mono> result = multiToMulti.apply(Tuples.of(firstFlux, secondFlux, thirdFlux)); - result.getT1().subscribe(v -> System.out.println("=> 1: " + v)); - result.getT2().subscribe(v -> System.out.println("=> 2: " + v)); - } - - @Test - @Disabled - public void testMultiToMultiWithMessageByteArrayPayload() { - FunctionCatalog catalog = this.configureCatalog(); - Function>, Flux>, Flux>>, Tuple2>, Mono>>> multiTuMulti = - catalog.lookup("multiToMulti", "foo/bar,application/json", "application/json"); - - Flux> firstFlux = Flux.just( - MessageBuilder.withPayload("Unlce".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build(), - MessageBuilder.withPayload("Onlce".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); - Flux> secondFlux = Flux.just( - MessageBuilder.withPayload("Sam".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build(), - MessageBuilder.withPayload("Pierre".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); - - ByteBuffer one = ByteBuffer.allocate(4); - one.putInt(1); - ByteBuffer two = ByteBuffer.allocate(4); - two.putInt(2); - - Flux> thirdFlux = Flux.just( - MessageBuilder.withPayload(one.array()).setHeader(MessageHeaders.CONTENT_TYPE, "octet-stream/integer").build(), - MessageBuilder.withPayload(two.array()).setHeader(MessageHeaders.CONTENT_TYPE, "octet-stream/integer").build()); - - Tuple2>, Mono>> result = multiTuMulti.apply(Tuples.of(firstFlux, secondFlux, thirdFlux)); - ObjectMapper mapper = new ObjectMapper(); - result.getT1().subscribe(v -> { - try { - System.out.println("=> 1: " + mapper.readValue(v.getPayload(), Person.class)); - } - catch (Exception e) { - e.printStackTrace(); - } - }); - result.getT2().subscribe(v -> { - try { - System.out.println("=> 2: " + mapper.readValue(v.getPayload(), Long.class)); - } - catch (Exception e) { - e.printStackTrace(); - } - }); - } - - - @EnableAutoConfiguration - @Configuration - protected static class SampleFunctionConfiguration { - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - // ============= MULTI-INPUT and MULTI-OUTPUT functions ============ - - @Bean - public Function, Flux>, Flux> multiInputSingleOutputViaReactiveTuple() { - return tuple -> { - Flux stringStream = tuple.getT1(); - Flux intStream = tuple.getT2(); - return Flux.zip(stringStream, intStream, (string, integer) -> string + "-" + integer); - }; - } - - @Bean - public BiFunction, Flux, Flux> multiInputSingleOutputViaBiFunction() { - return (in1, in2) -> { - Flux stringStream = in1; - Flux intStream = in2; - return Flux.zip(stringStream, intStream, (string, integer) -> string + "-" + integer); - }; - } - - @Bean - public Function, Tuple3, Flux, Flux>> multiOutputAsTuplePojoIn() { - return flux -> { - Flux pubSubFlux = flux.publish().autoConnect(3); - Flux nameFlux = pubSubFlux.map(person -> person.getName()); - Flux idFlux = pubSubFlux.map(person -> person.getId()); - return Tuples.of(pubSubFlux, nameFlux, idFlux); - }; - } - - @Bean - public Function>, Tuple3, Flux, Flux>> multiOutputAsTupleMessageIn() { - return flux -> { - Flux pubSubFlux = flux.map(message -> message.getPayload()).publish().autoConnect(3); - Flux nameFlux = pubSubFlux.map(person -> person.getName()); - Flux idFlux = pubSubFlux.map(person -> person.getId()); - return Tuples.of(pubSubFlux, nameFlux, idFlux); - }; - } - - @Bean - public Function, Flux, Flux>, Tuple2, Mono>> multiToMulti() { - return tuple -> { - Flux toStringFlux = tuple.getT1(); - Flux nameFlux = tuple.getT2(); - Flux idFlux = tuple.getT3(); - Flux person = toStringFlux.zipWith(nameFlux) - .map(t -> t.getT1() + " " + t.getT2()) - .zipWith(idFlux) - .map(t -> new Person(t.getT1(), t.getT2())); - return Tuples.of(person, person.count()); - }; - } - - @Bean - public MessageConverter byteArrayToIntegerMessageConverter() { - return new AbstractMessageConverter(MimeTypeUtils.parseMimeType("octet-stream/integer")) { - - @Override - protected boolean supports(Class clazz) { - return Integer.class.isAssignableFrom(clazz); - } - - @Override - protected Object convertFromInternal( - Message message, Class targetClass, @Nullable Object conversionHint) { - ByteBuffer wrappedPayload = ByteBuffer.wrap((byte[]) message.getPayload()); - return wrappedPayload.getInt(); - } - - @Override - protected Object convertToInternal( - Object payload, @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - - return null; - } - }; - } - - @Bean - public Function, Flux>, Flux[]> repeater() { - - return tuple -> { - Flux stringFlux = tuple.getT1(); - Flux integerFlux = tuple.getT2(); - - Flux sharedIntFlux = integerFlux.publish().autoConnect(2); - - Flux repeated = stringFlux - .zipWith(sharedIntFlux) - .flatMap(t -> Flux.fromIterable(Collections.nCopies(t.getT2(), t.getT1()))); - - Flux sum = sharedIntFlux - .buffer(3, 1) - .map(l -> l.stream().mapToInt(Integer::intValue).sum()); - - return new Flux[] { repeated, sum }; - }; - } - - @Bean - public Function, Flux>, Flux> thomas() { - return tuple -> { - Flux cartEventStream = tuple.getT1(); - Flux checkoutEventStream = tuple.getT2(); - - return Flux.zip(cartEventStream, checkoutEventStream, (cartEvent, checkoutEvent) -> { - OrderEvent oe = new OrderEvent(); - oe.setOrderEvent(cartEvent.toString() + "- " + checkoutEvent.toString()); - return oe; - }); - }; - } - } - - public static class CartEvent { - private String carEvent; - - public String getCarEvent() { - return carEvent; - } - - public void setCarEvent(String carEvent) { - this.carEvent = carEvent; - } - } - - public static class CheckoutEvent { - private String checkoutEvent; - - public String getCheckoutEvent() { - return checkoutEvent; - } - - public void setCheckoutEvent(String checkoutEvent) { - this.checkoutEvent = checkoutEvent; - } - } - - public static class OrderEvent { - private String orderEvent; - - public String getOrderEvent() { - return orderEvent; - } - - public void setOrderEvent(String orderEvent) { - this.orderEvent = orderEvent; - } - } - - public static class Person { - private String name; - private int id; - public Person() { - - } - public Person(String name, int id) { - this.name = name; - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - @Override - public String toString() { - return "Person: " + name + "/" + id; - } - } -} 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 deleted file mode 100644 index ebeb9dd94..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistryTests.java +++ /dev/null @@ -1,1436 +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.context.catalog; - - -import java.io.Serializable; -import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.databind.JsonNode; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuple3; -import reactor.util.function.Tuples; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -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.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.ReflectionUtils; - -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class BeanFactoryAwareFunctionRegistryTests { - - private ApplicationContext context; - - private FunctionCatalog configureCatalog() { - return this.configureCatalog(SampleFunctionConfiguration.class); - } - - private FunctionCatalog configureCatalog(Class... configClass) { - this.context = new SpringApplicationBuilder(configClass) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - @BeforeEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - } - - @Test - public void testFunctionEligibilityFiltering() { - System.setProperty("spring.cloud.function.ineligible-definitions", "asJsonNode"); - Collection registeredFunction = new ArrayList(); - FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class); - for (String beanName : context.getBeanDefinitionNames()) { - try { - FunctionInvocationWrapper function = catalog.lookup(beanName); - if (function != null && function.getFunctionDefinition().equals(beanName)) { - registeredFunction.add(function); - } - } - catch (Exception e) { - // ignore - } - } - System.out.println(registeredFunction); - assertThat(registeredFunction.size()).isEqualTo(2); - assertThat((FunctionInvocationWrapper) catalog.lookup("asJsonNode")).isNull(); - } - - @Test - public void testJsonNodeAsInput() throws Exception { - FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class); - Function, Message> f = catalog.lookup("messageAsJsonNode", "application/json"); - Message m = MessageBuilder.withPayload("[{\"name\":\"bob\"}, {\"name\":\"bob\"}]").setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build(); - assertThat(new String(f.apply(m).getPayload())).isEqualTo("[{\"name\":\"bob\"},{\"name\":\"bob\"}]"); - f = catalog.lookup("asJsonNode", "application/json"); - assertThat(new String(f.apply(m).getPayload())).isEqualTo("[{\"name\":\"bob\"},{\"name\":\"bob\"}]"); - } - - @SuppressWarnings({ "rawtypes" }) - @Test - public void concurrencyLookupTest() throws Exception { - FunctionCatalog catalog = this.configureCatalog(); - ExecutorService executor = Executors.newCachedThreadPool(); - for (int i = 0; i < 100; i++) { - executor.execute(() -> { - catalog.lookup("uppercase", "application/json"); - }); - executor.execute(() -> { - catalog.lookup("numberword", "application/json"); - }); - } - Thread.sleep(1000); - Field frField = ReflectionUtils.findField(catalog.getClass(), "functionRegistrations"); - frField.setAccessible(true); - Collection c = (Collection) frField.get(catalog); - assertThat(c.size()).isEqualTo(2); - } - - @Test - public void testReturnedMessageIsUnmodified() throws Exception { - FunctionCatalog catalog = this.configureCatalog(); - Function, Message> function = catalog.lookup("uppercaseMessage", "application/json"); - assertThat(function).isNotNull(); - - Message result = function.apply(MessageBuilder.withPayload("bob").setHeader("foo", "foo").build()); - assertThat(result.getHeaders().containsKey("foo")).isFalse(); - assertThat(result.getHeaders().containsKey("bar")).isTrue(); - } - - @SuppressWarnings("unchecked") - @Test - public void testDefaultLookup() throws Exception { - FunctionCatalog catalog = this.configureCatalog(); - Object function = catalog.lookup(""); - assertThat(function).isNull(); - //== - System.setProperty("spring.cloud.function.definition", "uppercase"); - catalog = this.configureCatalog(); - function = catalog.lookup(""); - assertThat(function).isNotNull(); -// Field field = ReflectionUtils.findField(FunctionInvocationWrapper.class, "composed"); -// field.setAccessible(true); - assertThat(((FunctionInvocationWrapper) function).isComposed()).isFalse(); - //== - System.setProperty("spring.cloud.function.definition", "uppercase|uppercaseFlux"); - catalog = this.configureCatalog(); -// function = catalog.lookup("", "application/json"); - function = catalog.lookup(""); - Function, Flux>> typedFunction = (Function, Flux>>) function; - Object blockFirst = typedFunction.apply(Flux.just("hello")).blockFirst(); - System.out.println(blockFirst); - assertThat(function).isNotNull(); -// field = ReflectionUtils.findField(FunctionInvocationWrapper.class, "composed"); -// field.setAccessible(true); -// assertThat(((boolean) field.get(function))).isTrue(); - assertThat(((FunctionInvocationWrapper) function).isComposed()).isTrue(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testBiFunction() { - FunctionCatalog catalog = this.configureCatalog(); - - Function biFunction = catalog.lookup("biFuncUpperCase"); - assertThat(biFunction.apply("hello")).isEqualTo("HELLO"); - } - - @Test - public void testImperativeFunction() { - FunctionCatalog catalog = this.configureCatalog(); - - Function>, Flux>> messageFlux = catalog.lookup("uppercase", "application/json"); - Message message1 = MessageBuilder.withPayload("\"uppercaseFlux\"".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build(); - Message message2 = MessageBuilder.withPayload("\"uppercaseFlux2\"".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build(); - List> messageResult = messageFlux.apply(Flux.just(message1, message2)).collectList().block(); - assertThat(messageResult.get(0).getPayload()).isEqualTo("\"UPPERCASEFLUX\"".getBytes(StandardCharsets.UTF_8)); - assertThat(messageResult.get(1).getPayload()).isEqualTo("\"UPPERCASEFLUX2\"".getBytes(StandardCharsets.UTF_8)); - } - - @Test - public void testConsumerFunction() { // function that returns Void, effectively a Consumer - FunctionCatalog catalog = this.configureCatalog(); - - Function consumerFunction = catalog.lookup("consumerFunction"); - assertThat(consumerFunction.apply("hello")).isNull(); - - Function, Void> consumerFunctionAsMessageA = catalog.lookup("consumerFunction"); - assertThat(consumerFunctionAsMessageA.apply(new GenericMessage("\"hello\"".getBytes()))).isNull(); - - Function, Void> consumerFunctionAsMessageB = catalog.lookup("consumerFunction", "application/json"); - assertThat(consumerFunctionAsMessageB.apply(new GenericMessage("\"hello\"".getBytes()))).isNull(); - } - - @Test - public void testMessageToPojoConversion() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Person> uppercasePerson = catalog.lookup("uppercasePerson"); - Person person = uppercasePerson.apply(MessageBuilder.withPayload("{\"name\":\"bill\",\"id\":2}").build()); - assertThat(person.getName()).isEqualTo("BILL"); - } - - /* - * When invoking imperative function as reactive the rules are - * - the input wrapper must match the output wrapper (e.g., or ) - */ - @Test - public void testImperativeVoidInputFunction() { - FunctionCatalog catalog = this.configureCatalog(); - - Function anyInputSignature = catalog.lookup("voidInputFunction"); - assertThat(anyInputSignature.apply(null)).isEqualTo("voidInputFunction"); - - Function asVoid = catalog.lookup("voidInputFunction"); - assertThat(asVoid.apply(null)).isEqualTo("voidInputFunction"); - } - - @Test - public void testReactiveVoidInputFunction() { - FunctionCatalog catalog = this.configureCatalog(); - - Function, Flux> voidInputFunctionReactive = catalog.lookup("voidInputFunctionReactive"); - List resultList = voidInputFunctionReactive.apply(Flux.empty()).collectList().block(); - assertThat(resultList.get(0)).isEqualTo("voidInputFunctionReactive"); - - Function> asVoid = catalog.lookup("voidInputFunctionReactive"); - resultList = asVoid.apply(null).collectList().block(); - assertThat(resultList.get(0)).isEqualTo("voidInputFunctionReactive"); - } - - @Test - public void testReactiveVoidInputFunctionAsSupplier() { - FunctionCatalog catalog = this.configureCatalog(); - Supplier> functionAsSupplier = catalog.lookup("voidInputFunctionReactive"); - List resultList = functionAsSupplier.get().collectList().block(); - assertThat(resultList.get(0)).isEqualTo("voidInputFunctionReactive"); - - Supplier> functionAsSupplier2 = catalog.lookup("voidInputFunctionReactive2"); - resultList = functionAsSupplier2.get().collectList().block(); - assertThat(resultList.get(0)).isEqualTo("voidInputFunctionReactive2"); - } - - - @Test - public void testComposition() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux> fluxFunction = catalog.lookup("uppercase|reverseFlux"); - - List result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0)).isEqualTo("OLLEH"); - assertThat(result.get(1)).isEqualTo("EYB"); - - fluxFunction = catalog.lookup("uppercase|reverse|reverseFlux"); - result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0)).isEqualTo("HELLO"); - assertThat(result.get(1)).isEqualTo("BYE"); - - fluxFunction = catalog.lookup("uppercase|reverseFlux|reverse"); - result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0)).isEqualTo("HELLO"); - assertThat(result.get(1)).isEqualTo("BYE"); - - fluxFunction = catalog.lookup("uppercase|reverse"); - result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0)).isEqualTo("OLLEH"); - assertThat(result.get(1)).isEqualTo("EYB"); - - Function function = catalog.lookup("uppercase|reverse"); - assertThat(function.apply("foo")).isEqualTo("OOF"); - } - - @Test - public void testCompositionSupplierAndFunction() { - FunctionCatalog catalog = this.configureCatalog(); - - Supplier> numberSupplierFlux = catalog.lookup("numberword|uppercaseFlux"); - String result = numberSupplierFlux.get().blockFirst(); - assertThat(result).isEqualTo("ONE"); - } - - /* - * This test should fail since the actual function is , hence we can - * not possibly convert Flux (which implies "many") to a single string. - * Further more, such flux will need to be triggered (e.g., subscribe(..) ) - */ - @SuppressWarnings("unused") - @Test - public void testReactiveFunctionWithImperativeInputAndOutputFail() { - FunctionCatalog catalog = this.configureCatalog(); - Function reverse = catalog.lookup("reverseFlux"); - Assertions.assertThrows(ClassCastException.class, () -> { - String result = reverse.apply("reverseFlux"); - }); - } - - @Test - public void testCompositionWithOutputConversion() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>> fluxFunction = catalog.lookup("uppercase|reverseFlux", "application/json"); - List> result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0).getPayload()).isEqualTo("\"OLLEH\"".getBytes()); - assertThat(result.get(1).getPayload()).isEqualTo("\"EYB\"".getBytes()); - - fluxFunction = catalog.lookup("uppercase|reverse|reverseFlux", "application/json"); - result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0).getPayload()).isEqualTo("\"HELLO\"".getBytes()); - assertThat(result.get(1).getPayload()).isEqualTo("\"BYE\"".getBytes()); - - fluxFunction = catalog.lookup("uppercase|reverseFlux|reverse", "application/json"); - result = fluxFunction.apply(Flux.just("hello", "bye")).collectList().block(); - assertThat(result.get(0).getPayload()).isEqualTo("\"HELLO\"".getBytes()); - assertThat(result.get(1).getPayload()).isEqualTo("\"BYE\"".getBytes()); - } - - @Test - public void testReactiveFunctionWithImperativeInputReactiveOutput() { - FunctionCatalog catalog = this.configureCatalog(); - Function> reverse = catalog.lookup("reverseFlux"); - List result = reverse.apply("reverse").collectList().block(); - assertThat(result.size()).isEqualTo(1); - assertThat(result.get(0)).isEqualTo("esrever"); - } - - @Test - public void testMonoVoidToMonoVoid() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Mono> monoToMono = catalog.lookup("monoVoidToMonoVoid"); - Void block = monoToMono.apply(Mono.empty()).block(); - assertThat(block).isNull(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void textTypeConversionWithComplexInputType() { - FunctionCatalog catalog = this.configureCatalog(ComplexTypeFunctionConfiguration.class); - Function function = catalog.lookup("function"); - - // as String - String result = (String) function.apply("{\"key\":\"purchase\",\"data\":{\"name\":\"bike\"}}"); - assertThat(result).isEqualTo("BIKE"); - - // as byte[] - result = (String) function.apply("{\"key\":\"purchase\",\"data\":{\"name\":\"bike\"}}".getBytes()); - assertThat(result).isEqualTo("BIKE"); - - // as Message - result = (String) function.apply(MessageBuilder.withPayload("{\"key\":\"purchase\",\"data\":{\"name\":\"bike\"}}").build()); - assertThat(result).isEqualTo("BIKE"); - - // as Message - result = (String) function.apply(MessageBuilder.withPayload("{\"key\":\"purchase\",\"data\":{\"name\":\"bike\"}}".getBytes()).build()); - assertThat(result).isEqualTo("BIKE"); - } - - // MULTI INPUT/OUTPUT - - - @Test - public void testMultiInput() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("multiInputSingleOutputViaReactiveTuple"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just(1, 2, 3); - - List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); - assertThat(result.size()).isEqualTo(3); - assertThat(result.get(0)).isEqualTo("one-1"); - assertThat(result.get(1)).isEqualTo("two-2"); - assertThat(result.get(2)).isEqualTo("three-3"); - } - - - //@Test - public void testMultiInputWithComposition() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Flux>, Flux> multiInputFunction = - catalog.lookup("multiInputSingleOutputViaReactiveTuple|uppercase"); - Flux stringStream = Flux.just("one", "two", "three"); - Flux intStream = Flux.just("1", "2", "3"); - - List result = multiInputFunction.apply(Tuples.of(stringStream, intStream)).collectList().block(); - assertThat(result.size()).isEqualTo(3); - assertThat(result.get(0)).isEqualTo("ONE-1"); - assertThat(result.get(1)).isEqualTo("TWO-2"); - assertThat(result.get(2)).isEqualTo("THREE-3"); - } - - - @Test - public void testMultiOutput() { - FunctionCatalog catalog = this.configureCatalog(); - Function, Tuple3, Flux, Flux>> multiOutputFunction = - catalog.lookup("multiOutputAsTuple"); - Flux personStream = Flux.just(new Person("Uncle Sam", 1), new Person("Oncle Pierre", 2)); - - Tuple3, Flux, Flux> result = multiOutputFunction.apply(personStream); - - result.getT1().subscribe(v -> System.out.println("=> 1: " + v)); - result.getT2().subscribe(v -> System.out.println("=> 2: " + v)); - result.getT3().subscribe(v -> System.out.println("=> 3: " + v)); - } - - @SuppressWarnings("rawtypes") - @Test - public void SCF_GH_409ConfigurationTests() { - FunctionCatalog catalog = this.configureCatalog(SCF_GH_409ConfigurationAsSupplier.class); - assertThat((Function) catalog.lookup("")).isNull(); - - catalog = this.configureCatalog(SCF_GH_409ConfigurationAsFunction.class); - assertThat((Function) catalog.lookup("")).isNull(); - } - - @Test - public void pojoFunctionAsJson() { - FunctionCatalog catalog = this.configureCatalog(); - Function uppercasePerson = catalog.lookup("uppercasePerson"); - - Person person = uppercasePerson.apply("{\"name\":\"bill\",\"id\":2}"); - assertThat(person.getName()).isEqualTo("BILL"); - } - - @Test - public void SCF_GH_429ConfigurationTests() throws Exception { - FunctionCatalog catalog = this.configureCatalog(MyFunction.class); - FunctionInvocationWrapper function = catalog.lookup("beanFactoryAwareFunctionRegistryTests.MyFunction"); - assertThat(function).isNotNull(); - Field f = ReflectionUtils.findField(FunctionInvocationWrapper.class, "composed"); - f.setAccessible(true); - boolean composed = (boolean) f.get(function); - assertThat(composed).isFalse(); - } - - @SuppressWarnings("unchecked") - @Test - @Disabled - public void byteArrayNoSpecialHandling() throws Exception { - FunctionCatalog catalog = this.configureCatalog(ByteArrayFunction.class); - FunctionInvocationWrapper function = catalog.lookup("beanFactoryAwareFunctionRegistryTests.ByteArrayFunction", "application/json"); - assertThat(function).isNotNull(); - Message result = (Message) function.apply(MessageBuilder.withPayload("hello".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "application/octet-stream").build()); - - System.out.println(new String(result.getPayload())); - - assertThat(result.getPayload()).isEqualTo("\"b2xsZWg=\"".getBytes()); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testMultipleValuesInOutputHandling() throws Exception { - FunctionCatalog catalog = this.configureCatalog(CollectionOutConfiguration.class); - FunctionInvocationWrapper function = catalog.lookup("parseToList", "application/json"); - assertThat(function).isNotNull(); - Object result = function.apply(MessageBuilder.withPayload("1,2,3".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); - assertThat(result instanceof Message).isTrue(); - byte[] payload = ((Message) result).getPayload(); - JsonMapper mapper = this.context.getBean(JsonMapper.class); - List resultList = mapper.fromJson(payload, List.class); - assertThat(resultList.size()).isEqualTo(3); - assertThat(resultList.get(0)).isEqualTo("1"); - assertThat(resultList.get(1)).isEqualTo("2"); - - function = catalog.lookup("parseToListOfMessages", "application/json"); - assertThat(function).isNotNull(); - result = function.apply(MessageBuilder.withPayload("1,2,3".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); - assertThat(result instanceof List).isTrue(); - } - - /** - * The following two tests test the fallback mechanism when an accept header has several values. - * The function produces Integer, which cannot be serialized by the default converter supporting text/plain - * (StringMessageConverter) but can by the one supporting application/json, which comes second. - */ - //@Test - public void testMultipleOrderedAcceptValues() throws Exception { - FunctionCatalog catalog = this.configureCatalog(MultipleOrderedAcceptValuesConfiguration.class); - Function> function = catalog.lookup("beanFactoryAwareFunctionRegistryTests.MultipleOrderedAcceptValuesConfiguration", "text/plain,application/json"); - assertThat(function).isNotNull(); - Message result = function.apply("hello"); - assertThat(result.getPayload()).isEqualTo("5".getBytes("UTF-8")); - } - - @Test - public void testMultipleOrderedAcceptValuesMessageOutput() throws Exception { - FunctionCatalog catalog = this.configureCatalog(MultipleOrderedAcceptValuesAsMessageOutputConfiguration.class); - Function> function = catalog.lookup( - "beanFactoryAwareFunctionRegistryTests.MultipleOrderedAcceptValuesAsMessageOutputConfiguration", - "text/plain,application/json"); - assertThat(function).isNotNull(); - Message result = function.apply("hello"); - assertThat(result.getPayload()).isEqualTo("5".getBytes("UTF-8")); - } - - @SuppressWarnings("unchecked") - @Test - public void testSerializationWithCompatibleWildcardSubtypeAcceptHeader() { - FunctionCatalog catalog = this.configureCatalog(NegotiatingMessageConverterConfiguration.class); - FunctionInvocationWrapper function = catalog.lookup("echo", "text/*"); - - Message> tupleResult = (Message>) function.apply(MessageBuilder - .withPayload(Tuples.of("bonjour", "monde")) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeType.valueOf("text/csv")) - .build() - ); - - assertThat(tupleResult.getHeaders().get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeType.valueOf("text/csv")); - assertThat(tupleResult.getHeaders().get("accept")).isNull(); - - Message dateResult = (Message) function.apply(MessageBuilder - .withPayload(123) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeType.valueOf("text/integer")) - .build() - ); - - assertThat(dateResult.getHeaders().get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeType.valueOf("text/integer")); - assertThat(dateResult.getHeaders().get("accept")).isNull(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testWithComplexHierarchyAndTypeConversion() { - FunctionCatalog catalog = this.configureCatalog(ReactiveFunctionImpl.class); - Function f = catalog.lookup(""); - assertThat(f.apply(new GenericMessage("23")).blockFirst()).isEqualTo(23); - assertThat(f.apply(Flux.just("25")).blockFirst()).isEqualTo(25); - assertThat(f.apply(Flux.just(25)).blockFirst()).isEqualTo(25); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testRegisteringWithTypeThatDoesNotMatchDiscoveredType() { - FunctionCatalog catalog = this.configureCatalog(EmptyConfiguration.class); - Function func = catalog.lookup("func"); - assertThat(func).isNull(); - FunctionRegistry registry = (FunctionRegistry) catalog; - try { - FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "a") - .type(FunctionTypeUtils.functionType(Integer.class, String.class)); - registry.register(registration); - fail(); - } - catch (IllegalArgumentException e) { - // good as we expect it to fail - } - // - try { - FunctionRegistration registration = new FunctionRegistration(new MyFunction(), "b") - .type(FunctionTypeUtils.functionType(String.class, Integer.class)); - registry.register(registration); - fail(); - } - catch (IllegalArgumentException e) { - // good as we expect it to fail - } - // - 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(FunctionTypeUtils.functionType(Person.class, String.class)); - registry.register(d); - // - FunctionRegistration e = new FunctionRegistration(new RawFunction(), "e") - .type(FunctionTypeUtils.functionType(Object.class, Object.class)); - registry.register(e); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testNoConversionOnInputMapIfInputIsMap() { - FunctionCatalog catalog = this.configureCatalog(); - Function f = catalog.lookup("maptopojo"); - Person p = new Person("John", 123); - Map map = new HashMap<>(); - map.put("person", p); - map.put("foo", "foo"); - assertThat(f.apply(map)).isInstanceOf(Person.class); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testValueWrappedInMessageIfNecessary() { - FunctionCatalog catalog = this.configureCatalog(PojoToMessageFunctionCompositionConfiguration.class); - Function f = catalog.lookup("uppercase|echo"); - assertThat(f.apply("hello")).isEqualTo("HELLO"); - f = catalog.lookup("toJson|uppercasePerson"); - assertThat(f.apply("Bubbles")).isEqualTo("BUBBLES"); - } - - @Test - public void testSupplierConsumerAsRunnable() { - FunctionCatalog catalog = this.configureCatalog(SampleFunctionConfiguration.class); - Runnable f = catalog.lookup("numberword|imperativeConsumer"); - f.run(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testWrappedWithAroundAdviseConfiguration() { - FunctionCatalog catalog = this.configureCatalog(WrappedWithAroundAdviseConfiguration.class); - Function f = catalog.lookup("uppercase"); - Message result = (Message) f.apply(new GenericMessage("hello")); - assertThat(result.getHeaders().get("before")).isEqualTo("foo"); - assertThat(result.getHeaders().get("after")).isEqualTo("bar"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testEachElementInFluxIsProcessed() { - FunctionCatalog catalog = this.configureCatalog(SampleFunctionConfiguration.class); - Function f = catalog.lookup("uppercasePerson"); - - Flux flux = Flux.just("{\"id\":1, \"name\":\"oleg\"}", "{\"id\":2, \"name\":\"seva\"}"); - Flux result = (Flux) f.apply(flux); - - List list = (List) result.collectList().block(); - assertThat(list.size()).isEqualTo(2); - assertThat(list.get(0).name).isEqualTo("OLEG"); - assertThat(list.get(1).name).isEqualTo("SEVA"); - - - - result = (Flux) f.apply(new GenericMessage("[{\"id\":1, \"name\":\"oleg\"}, {\"id\":2, \"name\":\"seva\"}]")); - list = (List) result.collectList().block(); - assertThat(list.size()).isEqualTo(2); - assertThat(list.get(0).name).isEqualTo("OLEG"); - assertThat(list.get(1).name).isEqualTo("SEVA"); - } - - @Test - public void testGH_608() { - ApplicationContext context = new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - Consumer> consumer = catalog.lookup("reactivePojoConsumer"); - consumer.accept(Flux.just("{\"name\":\"Ricky\"}")); - SampleFunctionConfiguration config = context.getBean(SampleFunctionConfiguration.class); - assertThat(((Person) config.consumerInputRef.get()).getName()).isEqualTo("Ricky"); - } - - @Test - public void testGH_611() { - FunctionCatalog catalog = this.configureCatalog(NegotiatingMessageConverterConfiguration.class); - Supplier> f = catalog.lookup("supplier", "text/*"); - assertThat(f.get().getHeaders().get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeTypeUtils.parseMimeType("text/*")); - } - - @Test - public void testGH_608_C() { - ApplicationContext context = new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - String productJson = "{\"key\":\"someKey\",\"data\": {\"name\":\"bike\"}}"; - - FunctionInvocationWrapper function = catalog.lookup("echoGenericObjectFlux", "application/json"); - Message result = ((Flux>) function.apply(productJson)).blockFirst(); - assertThat(new String(result.getPayload())).isEqualTo("\"bike\""); - } - - @Test - public void testGH_609() { - FunctionCatalog catalog = this.configureCatalog(SampleFunctionConfiguration.class); - Function, Publisher> f = catalog.lookup("monoToMono"); - Mono result = (Mono) f.apply(Mono.just("hello")); - assertThat(result.block()).isEqualTo("hello"); - - result = (Mono) f.apply(Flux.just("hello")); - assertThat(result.block()).isEqualTo("hello"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testGH_635() throws Exception { - FunctionCatalog catalog = this.configureCatalog(SCF_GH_635ConfigurationAsFunction.class); - Function lmFunction = catalog.lookup("emptyMessageList", "application/json"); - List> emptyListOfMessages = (List>) lmFunction.apply(MessageBuilder.withPayload("hello").build()); - assertThat(emptyListOfMessages).isEmpty(); - emptyListOfMessages = (List>) lmFunction.apply("hello"); - assertThat(emptyListOfMessages).isEmpty(); - - JsonMapper mapper = this.context.getBean(JsonMapper.class); - Function lsFunction = catalog.lookup("emptyStringList", "application/json"); - Message emptyListOfString = (Message) lsFunction.apply(MessageBuilder.withPayload("hello").build()); - List resultList = mapper.fromJson(emptyListOfString.getPayload(), List.class); - assertThat(resultList).isEmpty(); - emptyListOfString = (Message) lsFunction.apply("hello"); - resultList = mapper.fromJson(emptyListOfString.getPayload(), List.class); - assertThat(resultList).isEmpty(); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testGH_768() throws Exception { - FunctionCatalog catalog = this.configureCatalog(SCF_GH_768ConfigurationAsFunction.class); - Function function = catalog.lookup("echo"); - - JsonMapper mapper = this.context.getBean(JsonMapper.class); - String date = mapper.toString(new Date()); - String result = (String) function.apply("{\"date\":" + date + "}"); - assertThat(result).startsWith("{date="); - } - - @Test - public void test_791() { - try (ConfigurableApplicationContext ac = new SpringApplicationBuilder(InputHeaderPropagationConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true")) { - FunctionCatalog catalog = ac.getBean(FunctionCatalog.class); - - Function, Message> uppercase = catalog.lookup("uppercase", "application/json"); - Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHeader("foo", "bar").build()); - assertThat(result.getHeaders()).doesNotContainKey("foo"); - } - try (ConfigurableApplicationContext ac = new SpringApplicationBuilder(InputHeaderPropagationConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true", - "--spring.cloud.function.configuration.uppercase.copy-input-headers=true")) { - FunctionCatalog catalog = ac.getBean(FunctionCatalog.class); - - Function, Message> uppercase = catalog.lookup("uppercase", "application/json"); - Message result = uppercase.apply(MessageBuilder.withPayload("bob").setHeader("foo", "bar").build()); - assertThat(result.getHeaders()).containsKey("foo"); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testArrayPayloadOnFluxFunction() throws Exception { - FunctionCatalog catalog = this.configureCatalog(SampleFunctionConfiguration.class); - FunctionInvocationWrapper lmFunction = catalog.lookup("uppercaseFlux", "application/json"); - lmFunction.setSkipOutputConversion(true); - List list = new ArrayList<>(); - list.add("Ricky"); - list.add("Julien"); - list.add("Bubbles"); - Publisher p = (Publisher) lmFunction.apply(MessageBuilder.withPayload(list).setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); - List result = new ArrayList<>(); - for (Object value : Flux.from(p).toIterable()) { - result.add(value); - } - assertThat(result.size()).isEqualTo(3); - } - - @Test - // see GH-707 - public void testConcurrencyOnLookup() throws Exception { - AtomicInteger counter = new AtomicInteger(); - - ExecutorService executor = Executors.newFixedThreadPool(10); - for (int i = 0; i < 10; i++) { - FunctionCatalog catalog = this.configureCatalog(SampleFunctionConfiguration.class); - for (int y = 0; y < 10; y++) { - executor.execute(() -> { - assertThat((FunctionInvocationWrapper) catalog.lookup("uppercase|reverse", "application/json")).isNotNull(); - counter.incrementAndGet(); - }); - } - } - - executor.shutdown(); - executor.awaitTermination(10000, TimeUnit.MILLISECONDS); - assertThat(counter.get()).isEqualTo(100); - } - - @EnableAutoConfiguration - public static class PojoToMessageFunctionCompositionConfiguration { - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function, String> echo() { - return v -> v.getPayload(); - } - - @Bean - public Function toJson() { - return v -> "{\"id\":1, \"name\":\"" + v + "\"}"; - } - - @Bean - public Function, String> uppercasePerson() { - return v -> v.getPayload().getName().toUpperCase(); - } - } - - @EnableAutoConfiguration - @Configuration - public static class JsonNodeConfiguration { - @Bean - public Function, String> messageAsJsonNode() { - return v -> { - return v.getPayload().toString(); - }; - } - - @Bean - public Function asJsonNode() { - return v -> { - return v.toString(); - }; - } - } - - @EnableAutoConfiguration - public static class EmptyConfiguration { - - } - - public interface ReactiveFunction extends Function, Flux> { - - } - - @Component - @EnableAutoConfiguration - public static class ReactiveFunctionImpl implements ReactiveFunction { - @Override - public Flux apply(Flux inFlux) { - return inFlux.map(v -> Integer.parseInt(v)); - } - } - - @EnableAutoConfiguration - public static class CollectionOutConfiguration { - - @Bean - public Function> parseToList() { - return v -> Arrays.asList(v.split(",")); - } - - @Bean - public Function>> parseToListOfMessages() { - return v -> { - List> list = Arrays.asList(v.split(",")).stream() - .map(value -> MessageBuilder.withPayload(value).build()).collect(Collectors.toList()); - return list; - }; - } - } - - @EnableAutoConfiguration - public static class NegotiatingMessageConverterConfiguration { - - @Bean - public Supplier supplier() { - return () -> 123; - } - - @Bean - public Function echo() { - return v -> v; - } - - @Bean - public MessageConverter messageConverterA() { - return new ConverterA(); - } - - @Bean - public MessageConverter messageConverterB() { - return new ConverterB(); - } - - @Bean - public MessageConverter messageConverterC() { - return new ConverterC(); - } - - public static class ConverterC extends ConverterA { - ConverterC() { - super("text/*"); - } - - @Override - protected Object convertFromInternal( - Message message, Class targetClass, @Nullable Object conversionHint) { - return message.getPayload().toString(); - } - - @Override - public Object convertToInternal(Object rawPayload, MessageHeaders headers, Object conversionHint) { - return rawPayload; - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - return supportsMimeType(message.getHeaders()) && Integer.class.isAssignableFrom(targetClass) - && message.getPayload() instanceof Integer; - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - return payload instanceof Integer; - } - } - - public static class ConverterB extends ConverterA { - ConverterB() { - super("text/integer"); - } - - @Override - protected Object convertFromInternal( - Message message, Class targetClass, @Nullable Object conversionHint) { - return message.getPayload().toString(); - } - - @Override - public Object convertToInternal(Object rawPayload, MessageHeaders headers, Object conversionHint) { - return Integer.parseInt((String) rawPayload); - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - return supportsMimeType(message.getHeaders()) && String.class.isAssignableFrom(targetClass) - && message.getPayload() instanceof Integer; - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - return payload instanceof String; - } - } - - private static class ConverterA extends AbstractMessageConverter { - - ConverterA() { - this("text/csv"); - } - - ConverterA(String mimeType) { - super(singletonList(MimeType.valueOf(mimeType))); - } - - @SuppressWarnings("unchecked") - @Override - protected Object convertFromInternal( - Message message, Class targetClass, @Nullable Object conversionHint) { - Tuple2 payload = (Tuple2) message.getPayload(); - - String convertedPayload = payload.getT1() + "," + payload.getT2(); - return convertedPayload; - } - - @Override - public Object convertToInternal(Object rawPayload, MessageHeaders headers, Object conversionHint) { - return Tuples.fromArray(((String) rawPayload).split(",")); - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - return supportsMimeType(message.getHeaders()) && String.class.isAssignableFrom(targetClass) - && message.getPayload() instanceof Tuple2; - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - return payload instanceof String && ((String) payload).split(",").length == 2; - } - - @Override - protected boolean supports(Class clazz) { - throw new UnsupportedOperationException(); - } - } - } - - @EnableAutoConfiguration - @Configuration - protected static class WrappedWithAroundAdviseConfiguration { - @Bean - public Function, Message> uppercase() { - return v -> MessageBuilder.withPayload(v.getPayload().toUpperCase()).copyHeaders(v.getHeaders()).build(); - } - - @Bean - @ConditionalOnMissingBean - public FunctionAroundWrapper wrapper() { - return new FunctionAroundWrapper() { - - @SuppressWarnings("unchecked") - @Override - protected Object doApply(Object input, FunctionInvocationWrapper targetFunction) { - // in this test we know input is a Message - Message mInput = (Message) input; - MessageBuilder.fromMessage(mInput).setHeader("before", "foo").build(); - Message result = (Message) targetFunction.apply(MessageBuilder.fromMessage(mInput).setHeader("before", "foo").build()); - return MessageBuilder.fromMessage(result).setHeader("after", "bar").build(); - } - }; - } - } - - @EnableAutoConfiguration - @Configuration - protected static class InputHeaderPropagationConfiguration { - - @Bean - public Function uppercase() { - return x -> x.toUpperCase(); - } - } - - @EnableAutoConfiguration - @Configuration - protected static class SampleFunctionConfiguration { - - AtomicReference consumerInputRef = new AtomicReference<>(); - - @Bean - public Function>>, Flux> echoGenericObjectFlux() { - return x -> x.map(eventMessage -> eventMessage.getPayload().getData().getName()); - } - - @Bean - public Function uppercasePerson() { - return person -> { - return new Person(person.getName().toUpperCase(), person.getId()); - }; - } - - @Bean - public Supplier numberword() { - return () -> "one"; - } - - @Bean - public BiFunction biFuncUpperCase() { - return (p, h) -> { - return p.toUpperCase(); - }; - } - - @Bean - public Function, Person> maptopojo() { - return map -> { - Person person = (Person) map.get("person"); - return person; - }; - } - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function, Message> uppercaseMessage() { - return message -> { - Message result = MessageBuilder.fromMessage(message) - .removeHeader("foo").setHeader("bar", "bar").build(); - return result; - }; - } - - @Bean - public Function consumerFunction() { - return v -> { - System.out.println("Value: " + v); - return null; - }; - } - - @Bean - public Function, Flux> uppercaseFlux() { - return flux -> flux.map(v -> v.toUpperCase()); - } - - @Bean - public Function voidInputFunction() { - return v -> "voidInputFunction"; - } - - @Bean - public Function, Flux> voidInputFunctionReactive() { - return flux -> Flux.just("voidInputFunctionReactive"); - } - - @Bean - public Function, Flux> voidInputFunctionReactive2() { - return mono -> Flux.just("voidInputFunctionReactive2"); - } - - @Bean - public Function reverse() { - return value -> new StringBuilder(value).reverse().toString(); - } - - @Bean - public Function, Flux> reverseFlux() { - return flux -> flux.map(value -> { - return new StringBuilder(value).reverse().toString(); - }); - } - - - @Bean - public Function, Mono> monoVoidToMonoVoid() { - return mono -> mono.doOnSuccess(v -> System.out.println("HELLO")); - } - - // ============= MESSAGE-IN and MESSAGE-OUT functions ============ - - // ============= MULTI-INPUT and MULTI-OUTPUT functions ============ - - @Bean - public Function, Flux>, Flux> multiInputSingleOutputViaReactiveTuple() { - return tuple -> { - Flux stringStream = tuple.getT1(); - Flux intStream = tuple.getT2(); - return Flux.zip(stringStream, intStream, (string, integer) -> string + "-" + integer); - }; - } - //======== - - // MULTI-OUTPUT - @Bean - public Function, Tuple3, Flux, Flux>> multiOutputAsTuple() { - return flux -> { - Flux pubSubFlux = flux.publish().autoConnect(3); - Flux nameFlux = pubSubFlux.map(person -> person.getName()); - Flux idFlux = pubSubFlux.map(person -> person.getId()); - return Tuples.of(pubSubFlux, nameFlux, idFlux); - }; - } - - public Function, Flux>> multiOutputAsTuple2() { - return null; - } - //======== - - @Bean - public Function, Mono> monoToMonoVoid() { - return null; - } - - @Bean - public Function, Mono> monoToMono() { - return mono -> mono; - } - - @Bean - public Function, Flux> fluxVoidToFluxVoid() { - return null; - } - - @Bean - public Function, Flux> monoToFluxVoid() { - return null; - } - - @Bean - public Function, Mono> fluxToMonoVoid() { - return null; - } - - @Bean - public Function, Flux> monoToFlux() { - return null; - } - - @Bean - public Function, Mono> fluxToMono() { - return null; - } - - @Bean - public Supplier imperativeSupplier() { - return null; - } - - @Bean - public Supplier> reactiveSupplier() { - return null; - } - - @Bean - public Consumer imperativeConsumer() { - return System.out::println; - } - - @Bean - // Perhaps it should not be allowed. Recommend Function> - public Consumer> reactiveConsumer() { - return null; - } - - @Bean - // Perhaps it should not be allowed. Recommend Function> - public Consumer> reactivePojoConsumer() { - return flux -> flux.subscribe(v -> consumerInputRef.set(v)); - } - } - - @EnableAutoConfiguration - public static class SCF_GH_409ConfigurationAsSupplier { - - @Bean - public Serializable blah() { - return new Foo(); - } - - private static class Foo implements Supplier, Serializable { - - @Override - public Object get() { - // TODO Auto-generated method stub - return null; - } - - } - } - - @EnableAutoConfiguration - public static class SCF_GH_409ConfigurationAsFunction { - - @Bean - public Serializable blah() { - return new Foo(); - } - - private static class Foo implements Function, Serializable { - - @Override - public Object apply(Object t) { - // TODO Auto-generated method stub - return null; - } - } - } - - @EnableAutoConfiguration - public static class SCF_GH_635ConfigurationAsFunction { - - @Bean - public Function>> emptyMessageList() { - return input -> Collections.emptyList(); - } - - @Bean - public Function> emptyStringList() { - return input -> Collections.emptyList(); - } - } - - @EnableAutoConfiguration - public static class SCF_GH_768ConfigurationAsFunction { - @Bean - public Function, String> echoToString() { - return data -> { - for (Entry dataEntry : data.entrySet()) { - assertThat(dataEntry.getValue()).isInstanceOf(Date.class); // would fail if value would not be converted to Person - } - return data.toString(); - }; - } - } - - public static class Person { - private String name; - private int id; - public Person() { - - } - public Person(String name, int id) { - this.name = name; - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - @Override - public String toString() { - return "Person: " + name + "/" + id; - } - } - - @EnableAutoConfiguration - @Configuration - @Component - public static class MyFunction implements Function { - - @Override - public String apply(String t) { - return t; - } - - } - - public static class RawFunction implements Function { - - @Override - public Object apply(Object t) { - return t; - } - - } - - @EnableAutoConfiguration - @Configuration - @Component - public static class ByteArrayFunction implements Function { - - @Override - public byte[] apply(byte[] bytes) { - byte[] result = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) { - result[i] = bytes[bytes.length - i - 1]; - } - return result; - } - } - - @EnableAutoConfiguration - @Configuration - @Component - public static class MultipleOrderedAcceptValuesConfiguration implements Function { - - @Override - public Integer apply(String t) { - return t.length(); - } - } - - @EnableAutoConfiguration - @Configuration - @Component - public static class MultipleOrderedAcceptValuesAsMessageOutputConfiguration implements Function> { - - @Override - public Message apply(String t) { - return MessageBuilder.withPayload(t.length()).build(); - } - - } - - @EnableAutoConfiguration - @Configuration - public static class ComplexTypeFunctionConfiguration { - @Bean - public Function, String> function() { - return v -> v.getData().getName().toUpperCase(); - } - } - - private static class Product { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - private static class Event { - - private K key; - - public K getKey() { - return key; - } - - public void setKey(K key) { - this.key = key; - } - - private V data; - - public V getData() { - return data; - } - - public void setData(V data) { - this.data = data; - } - } -} 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 deleted file mode 100644 index accc4c5ba..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwarePojoFunctionRegistryTests.java +++ /dev/null @@ -1,141 +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.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class BeanFactoryAwarePojoFunctionRegistryTests { - - private FunctionCatalog configureCatalog() { - ApplicationContext context = new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .run("--logging.level.org.springframework.cloud.function=DEBUG"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - @Test - public void testWithPojoFunctionImplementingFunction() { - FunctionCatalog catalog = this.configureCatalog(); - -// MyFunction f1 = catalog.lookup("myFunction"); -// assertThat(f1.uppercase("foo")).isEqualTo("FOO"); - - Function f2 = catalog.lookup("myFunction"); - assertThat(f2.apply("foo")).isEqualTo("FOO"); - - Function f2conversion = catalog.lookup("myFunction"); - assertThat(f2conversion.apply(123)).isEqualTo("123"); - - Function, String> f2message = catalog.lookup("myFunction"); - assertThat(f2message.apply(MessageBuilder.withPayload("message").build())).isEqualTo("MESSAGE"); - - Function, Flux> f3 = catalog.lookup("myFunction"); - assertThat(f3.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - - Function, Message> f2messageReturned = catalog.lookup("myFunction", "application/json"); - assertThat(new String(f2messageReturned.apply(MessageBuilder.withPayload("message").build()).getPayload())).isEqualTo("\"MESSAGE\""); - } - - @Test - public void testWithPojoFunction() { - FunctionCatalog catalog = this.configureCatalog(); - -// MyFunctionLike f1 = catalog.lookup("myFunctionLike"); -// assertThat(f1.uppercase("foo")).isEqualTo("FOO"); - - Function f2 = catalog.lookup("myFunctionLike"); - assertThat(f2.apply("foo")).isEqualTo("FOO"); - - Function f2conversion = catalog.lookup("myFunctionLike"); - assertThat(f2conversion.apply(123)).isEqualTo("123"); - - Function, String> f2message = catalog.lookup("myFunctionLike"); - assertThat(f2message.apply(MessageBuilder.withPayload("message").build())).isEqualTo("MESSAGE"); - - Function, Flux> f3 = catalog.lookup("myFunctionLike"); - assertThat(f3.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - - Function, Message> f2messageReturned = catalog.lookup("myFunctionLike", "application/json"); - assertThat(new String(f2messageReturned.apply(MessageBuilder.withPayload("message").build()).getPayload())).isEqualTo("\"MESSAGE\""); - } - - @Test - public void testWithPojoFunctionComposition() { - FunctionCatalog catalog = this.configureCatalog(); - Function f1 = catalog.lookup("myFunction|myFunctionLike|func"); - assertThat(f1.apply("foo")).isEqualTo("FOO"); - } - - - @EnableAutoConfiguration - @Configuration - protected static class SampleFunctionConfiguration { - - @Bean - public MyFunction myFunction() { - return new MyFunction(); - } - - @Bean - public MyFunctionLike myFunctionLike() { - return new MyFunctionLike(); - } - - @Bean - public Function func() { - return v -> v; - } - } - - // POJO Function that implements Function - private static class MyFunction implements Function { - public String uppercase(String value) { - return value.toUpperCase(); - } - - @Override - public String apply(String t) { - return this.uppercase(t); - } - } - - // POJO Function - 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 deleted file mode 100644 index ee1dfb29b..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtilsTests.java +++ /dev/null @@ -1,208 +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.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -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.core.publisher.Mono; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuple3; - -import org.springframework.core.MethodParameter; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.messaging.Message; -import org.springframework.util.ReflectionUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -@SuppressWarnings("unused") -public class FunctionTypeUtilsTests { - - @Test - public void testFunctionTypeFrom() throws Exception { - Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(SimpleConsumer.class); - assertThat(type).isInstanceOf(ParameterizedType.class); - Type wrapperType = ((ParameterizedType) type).getActualTypeArguments()[0]; - assertThat(wrapperType).isInstanceOf(ParameterizedType.class); - assertThat(wrapperType.getTypeName()).contains("Flux"); - - Type innerWrapperType = ((ParameterizedType) wrapperType).getActualTypeArguments()[0]; - assertThat(innerWrapperType).isInstanceOf(ParameterizedType.class); - assertThat(innerWrapperType.getTypeName()).contains("Message"); - - Type targetType = ((ParameterizedType) innerWrapperType).getActualTypeArguments()[0]; - assertThat(targetType).isEqualTo(String.class); - System.out.println(); - } - - @Test - public void testFunctionTypeByClassDiscovery() { - Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(Function.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getInputType(type))).isAssignableFrom(Object.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 = FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageFunction.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfOutputType(type))).isAssignableFrom(String.class); - - type = FunctionTypeUtils.discoverFunctionTypeFromClass(MessageConsumer.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); - - type = FunctionTypeUtils.discoverFunctionTypeFromClass(MyMessageConsumer.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getComponentTypeOfInputType(type))).isAssignableFrom(String.class); - } - - @Test - public void testWithComplexHierarchy() { - 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 - public void testIsTypeCollection() { - assertThat(FunctionTypeUtils.isTypeCollection(new ParameterizedTypeReference() { }.getType())).isFalse(); - assertThat(FunctionTypeUtils.isTypeCollection(new ParameterizedTypeReference>() { }.getType())).isTrue(); - assertThat(FunctionTypeUtils.isTypeCollection(new ParameterizedTypeReference>>() { }.getType())).isTrue(); - assertThat(FunctionTypeUtils.isTypeCollection(new ParameterizedTypeReference>>>() { }.getType())).isTrue(); - assertThat(FunctionTypeUtils.isTypeCollection(new ParameterizedTypeReference>>>() { }.getType())).isFalse(); - } - - @Test - public void testNoNpeFromIsMessage() { - FunctionTypeUtilsTests testService = new FunctionTypeUtilsTests<>(); - - Method methodUnderTest = - ReflectionUtils.findMethod(testService.getClass(), "notAMessageMethod", AtomicReference.class); - MethodParameter methodParameter = MethodParameter.forExecutable(methodUnderTest, 0); - - assertThat(FunctionTypeUtils.isMessage(methodParameter.getGenericParameterType())).isFalse(); - } - - void notAMessageMethod(AtomicReference payload) { - - } - - private static Function function() { - return null; - } - - @SuppressWarnings("rawtypes") - private static Function typelessFunction() { - return null; - } - - private static Function, Tuple3> multiInputOutputFunction() { - return null; - } - - private static Function, Mono>, - Tuple3, Flux, Mono>> multiInputOutputPublisherFunction() { - return null; - } - - private static Function>, Mono>, - Tuple3>, Flux, Mono>> multiInputOutputPublisherFunctionComplexTypes() { - return null; - } - - private static Consumer consumer() { - return null; - } - - private static Consumer> multiInputConsumer() { - return null; - } - - @SuppressWarnings("rawtypes") - private static Consumer typelessConsumer() { - return null; - } - - private static Supplier supplier() { - return null; - } - - @SuppressWarnings("rawtypes") - private static Supplier typelessSupplier() { - return null; - } - - private static Supplier> multiOutputSupplier() { - return null; - } - - private Type getReturnType(String methodName) throws Exception { - return FunctionTypeUtilsTests.class.getDeclaredMethod(methodName).getGenericReturnType(); - } - - //============ - - private interface MessageFunction extends Function, Message> { - - } - - private interface MyMessageFunction extends MessageFunction { - - } - - private interface MessageConsumer extends Consumer> { - - } - - private interface MyMessageConsumer extends MessageConsumer { - - } - - public static class SimpleConsumer implements Consumer>> { - @Override - public void accept(Flux> messageFlux) { - } - } - - public interface ReactiveFunction extends Function, Flux> { - - } - - public static class ReactiveFunctionImpl implements ReactiveFunction { - - @Override - public Flux apply(Flux inFlux) { - return inFlux.map(v -> Integer.parseInt(v)); - } - } -} 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 deleted file mode 100644 index 4314ee669..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright 2012-2023 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.Field; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -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.HybridFunctionalRegistrationTests.UppercaseFunction; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.JsonMessageConverter; -import org.springframework.cloud.function.context.config.SmartCompositeMessageConverter; -import org.springframework.cloud.function.json.GsonMapper; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.core.ResolvableType; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.ByteArrayMessageConverter; -import org.springframework.messaging.converter.CompositeMessageConverter; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.converter.StringMessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; -import org.springframework.util.ReflectionUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - * @author Soby Chacko - * @author Chris Bono - */ -public class SimpleFunctionRegistryTests { - - private CompositeMessageConverter messageConverter; - - private ConversionService conversionService; - - @BeforeEach - public void before() { - List messageConverters = new ArrayList<>(); - JsonMapper jsonMapper = new GsonMapper(new Gson()); - messageConverters.add(new JsonMessageConverter(jsonMapper)); - messageConverters.add(new ByteArrayMessageConverter()); - messageConverters.add(new StringMessageConverter()); - this.messageConverter = new SmartCompositeMessageConverter(messageConverters); - - this.conversionService = new DefaultConversionService(); - } - - @SuppressWarnings("rawtypes") - @Test - public void concurrencyRegistrationTest() throws Exception { - Echo function = new Echo(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(Echo.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - ExecutorService executor = Executors.newCachedThreadPool(); - for (int i = 0; i < 1000; i++) { - executor.execute(() -> { - catalog.register(registration); - }); - } - Thread.sleep(1000); - Field frField = ReflectionUtils.findField(catalog.getClass(), "functionRegistrations"); - frField.setAccessible(true); - Collection c = (Collection) frField.get(catalog); - assertThat(c.size()).isEqualTo(1); - } - - @Test - public void testCachingOfFunction() { - Echo function = new Echo(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(Echo.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper instanceA = catalog.lookup("echo", "application/json"); - FunctionInvocationWrapper instanceb = catalog.lookup("echo", "text/plain"); - FunctionInvocationWrapper instanceC = catalog.lookup("echo", "foo/bar"); - - assertThat(instanceA).isSameAs(instanceb).isSameAs(instanceC); - } - - @Test - public void testNoCachingOfFunction() { - Echo function = new Echo(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(Echo.class); - registration.getProperties().put("singleton", "false"); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper instanceA = catalog.lookup("echo", "application/json"); - FunctionInvocationWrapper instanceb = catalog.lookup("echo", "text/plain"); - FunctionInvocationWrapper instanceC = catalog.lookup("echo", "foo/bar"); - - assertThat(instanceA).isNotSameAs(instanceb).isNotSameAs(instanceC); - } - - @Test - public void testSCF768() { - ResolvableType map = ResolvableType.forClassWithGenerics(Map.class, String.class, Person.class); - Type functionType = ResolvableType.forClassWithGenerics(Function.class, map, ResolvableType.forClass(String.class)).getType(); - - Function, String> function = persons -> { - for (Entry entry : persons.entrySet()) { - assertThat(entry.getValue().getName()).isNotEmpty(); // would fail if value would not be converted to Person - } - return persons.toString(); - }; - - FunctionRegistration, String>> registration = new FunctionRegistration<>( - function, "echo").type(functionType); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper lookedUpFunction = catalog.lookup("echo"); - String result = (String) lookedUpFunction.apply("{\"ricky\":{\"name\":\"ricky\"}}"); - assertThat(result).isEqualTo("{ricky=ricky}"); - } - - @Test - public void testSCF640() { - Echo function = new Echo(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "echo").type(Echo.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper lookedUpFunction = catalog.lookup("echo"); - Object result = lookedUpFunction.apply("{\"HELLO\":\"WORLD\"}"); - assertThat(result).isNotInstanceOf(Message.class); - assertThat(result).isEqualTo("{\"HELLO\":\"WORLD\"}"); - } - - @ParameterizedTest - @ValueSource(strings = {"[hello", "hello]", "[hello]"}) - void textContentTypeWithValueWrappedBracketsIsOk(String inputMessagePayloadValue) { - var catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper())); - catalog.register(new FunctionRegistration<>(new Echo(), "echo").type(Echo.class)); - FunctionInvocationWrapper lookedUpFunction = catalog.lookup("echo"); - var inputMessage = MessageBuilder.withPayload(inputMessagePayloadValue) - .setHeader("contentType", "text/plain") - .build(); - var functionResult = lookedUpFunction.apply(inputMessage); - assertThat(functionResult).isEqualTo(inputMessagePayloadValue); - } - - @SuppressWarnings("unchecked") - @Test - public void testSCF762() { - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - - FunctionRegistration reg1 = new FunctionRegistration<>( - new UpperCase(), "uppercase").type(UpperCase.class); - catalog.register(reg1); - // - FunctionRegistration reg2 = new FunctionRegistration<>( - new UpperCaseMessage(), "uppercaseMessage").type(UpperCaseMessage.class); - catalog.register(reg2); - // - FunctionRegistration reg3 = new FunctionRegistration<>( - new StringArrayFunction(), "stringArray").type(StringArrayFunction.class); - catalog.register(reg3); - // - FunctionRegistration reg4 = new FunctionRegistration<>( - new TypelessFunction(), "typeless").type(TypelessFunction.class); - catalog.register(reg4); - // - FunctionRegistration reg5 = new FunctionRegistration<>( - new ByteArrayFunction(), "typeless").type(ByteArrayFunction.class); - catalog.register(reg5); - // - FunctionRegistration reg6 = new FunctionRegistration<>( - new StringListFunction(), "stringList").type(StringListFunction.class); - catalog.register(reg6); - - Message collectionMessage = MessageBuilder.withPayload("[\"ricky\", \"julien\", \"bubbles\"]").build(); - Message singleValueMessage = MessageBuilder.withPayload("\"ricky\"").build(); - - FunctionInvocationWrapper lookedUpFunction = catalog.lookup("uppercase", "application/json"); - Object result = lookedUpFunction.apply(singleValueMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("\"RICKY\"".getBytes()); - - result = lookedUpFunction.apply(collectionMessage); - assertThat(result).isInstanceOf(Flux.class); - List> collectionIfResults = Flux.from((Publisher>) result).collectList().block(); - assertThat(collectionIfResults.size()).isEqualTo(3); - assertThat(collectionIfResults.get(0).getPayload()).isEqualTo("\"RICKY\"".getBytes()); - assertThat(collectionIfResults.get(1).getPayload()).isEqualTo("\"JULIEN\"".getBytes()); - - lookedUpFunction = catalog.lookup("typeless", "application/json"); - result = lookedUpFunction.apply(singleValueMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("\"ricky\"".getBytes()); - - result = lookedUpFunction.apply(collectionMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("[\"ricky\", \"julien\", \"bubbles\"]".getBytes()); - - - lookedUpFunction = catalog.lookup("stringArray", "application/json"); - result = lookedUpFunction.apply(singleValueMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("[\"ricky\"]".getBytes()); - - result = lookedUpFunction.apply(collectionMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("[ricky, julien, bubbles]".getBytes()); - - - lookedUpFunction = catalog.lookup("stringList", "application/json"); - result = lookedUpFunction.apply(singleValueMessage); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("[\"ricky\"]".getBytes()); - - result = lookedUpFunction.apply(collectionMessage); - assertThat(result).isInstanceOf(Message.class); - System.out.println(new String(((Message) result).getPayload())); - assertThat(((Message) result).getPayload()).isEqualTo("[ricky, julien, bubbles]".getBytes()); - - } - - @SuppressWarnings("unchecked") - @Test - public void testSCF588() { - - UpperCase function = new UpperCase(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "foo").type(UppercaseFunction.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper lookedUpFunction = catalog.lookup("uppercase"); - Message message = MessageBuilder.withPayload("hello") - .setHeader("lambda-runtime-aws-request-id", UUID.randomUUID()) - .build(); - Object result = lookedUpFunction.apply(message); - assertThat(result).isInstanceOf(Message.class); - assertThat(((Message) result).getPayload()).isEqualTo("HELLO"); - } - - @Test - public void testFunctionLookup() { - - TestFunction function = new TestFunction(); - FunctionRegistration registration = new FunctionRegistration<>( - function, "foo").type(TestFunction.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - //FunctionInvocationWrapper lookedUpFunction = catalog.lookup("hello"); - 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(TestFunction.class); - catalog.register(registration2); - lookedUpFunction = catalog.lookup("hello"); - assertThat(lookedUpFunction).isNull(); - } - - - - @Test - public void testFunctionComposition() { - FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( - new UpperCase(), "uppercase").type(UpperCase.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(Reverse.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(upperCaseRegistration); - catalog.register(reverseRegistration); - - Function, Flux> lookedUpFunction = catalog - .lookup("uppercase|reverse"); - assertThat(lookedUpFunction).isNotNull(); - } - - @Test - @Disabled - public void testFunctionCompositionImplicit() { - FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(Words.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(Reverse.class); - FunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(wordsRegistration); - catalog.register(reverseRegistration); - - // There's only one function, we should be able to leave that blank - Supplier lookedUpFunction = catalog.lookup("words|"); - - assertThat(lookedUpFunction).isNotNull(); - assertThat(lookedUpFunction.get()).isEqualTo("olleh"); - } - - @Test - @Disabled - public void testFunctionCompletelyImplicitComposition() { - FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(Words.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(Reverse.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(wordsRegistration); - catalog.register(reverseRegistration); - - // There's only one function, we should be able to leave that blank - Supplier> lookedUpFunction = catalog.lookup("|"); - - assertThat(lookedUpFunction).isNotNull(); - assertThat(lookedUpFunction.get().blockFirst()).isEqualTo("olleh"); - } - - @Test - public void testFunctionCompositionExplicit() { - FunctionRegistration wordsRegistration = new FunctionRegistration<>( - new Words(), "words").type(Words.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(Reverse.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(wordsRegistration); - catalog.register(reverseRegistration); - - Supplier lookedUpFunction = catalog.lookup("words|reverse"); - - assertThat(lookedUpFunction).isNotNull(); - assertThat(lookedUpFunction.get()).isEqualTo("olleh"); - } - - @Test - public void testFunctionCompositionWithMessages() { - FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( - new UpperCaseMessage(), "uppercase") - .type(UpperCaseMessage.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new ReverseMessage(), "reverse") - .type(ReverseMessage.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(upperCaseRegistration); - catalog.register(reverseRegistration); - - Function>, Flux>> lookedUpFunction = catalog - .lookup("uppercase|reverse"); - - assertThat(lookedUpFunction).isNotNull(); - assertThat(lookedUpFunction - .apply(Flux.just(MessageBuilder.withPayload("star").build())).blockFirst() - .getPayload()).isEqualTo("RATS"); - } - - @Test - public void testFunctionCompositionMixedMessages() { - FunctionRegistration upperCaseRegistration = new FunctionRegistration<>( - new UpperCaseMessage(), "uppercase") - .type(UpperCaseMessage.class); - FunctionRegistration reverseRegistration = new FunctionRegistration<>( - new Reverse(), "reverse").type(Reverse.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(upperCaseRegistration); - catalog.register(reverseRegistration); - - Function, String> lookedUpFunction = catalog - .lookup("uppercase|reverse"); - - assertThat(lookedUpFunction).isNotNull(); - String result = lookedUpFunction.apply(MessageBuilder.withPayload("star").setHeader("foo", "bar").build()); - assertThat(result).isEqualTo("RATS"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testReactiveFunctionMessages() { - FunctionRegistration registration = new FunctionRegistration<>(new ReactiveFunction(), "reactive") - .type(ReactiveFunction.class); - - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - Function lookedUpFunction = catalog.lookup("reactive"); - - assertThat(lookedUpFunction).isNotNull(); - Flux> result = (Flux>) lookedUpFunction - .apply(Flux.just(MessageBuilder - .withPayload("[{\"name\":\"item1\"},{\"name\":\"item2\"}]") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .build() - )); - - Assertions.assertIterableEquals(result.blockFirst(), Arrays.asList("item1", "item2")); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testWithCustomMessageConverter() { - FunctionCatalog catalog = this.configureCatalog(CustomConverterConfiguration.class); - Function function = catalog.lookup("func"); - Object result = function.apply(MessageBuilder.withPayload("Jim Lahey").setHeader(MessageHeaders.CONTENT_TYPE, "text/person").build()); - assertThat(result).isEqualTo("Jim Lahey"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void lookup() { - SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - FunctionInvocationWrapper function = functionRegistry.lookup("uppercase"); - assertThat(function).isNull(); - - Function userFunction = uppercase(); - FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "uppercase") - .type(FunctionTypeUtils.functionType(String.class, String.class)); - functionRegistry.register(functionRegistration); - - function = functionRegistry.lookup("uppercase"); - assertThat(function).isNotNull(); - } - - - @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(FunctionTypeUtils.functionType(String.class, String.class)); - functionRegistry.register(functionRegistration); - - FunctionInvocationWrapper function = functionRegistry.lookup(""); - assertThat(function).isNotNull(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void lookupWithCompositionFunctionAndConsumer() { - SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - - Object userFunction = uppercase(); - FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "uppercase") - .type(FunctionTypeUtils.functionType(String.class, String.class)); - functionRegistry.register(functionRegistration); - - userFunction = consumer(); - functionRegistration = new FunctionRegistration(userFunction, "consumer") - .type(ResolvableType.forClassWithGenerics(Consumer.class, Integer.class).getType()); - functionRegistry.register(functionRegistration); - - FunctionInvocationWrapper functionWrapper = functionRegistry.lookup("uppercase|consumer"); - - functionWrapper.apply("123"); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void lookupWithReactiveConsumer() { - SimpleFunctionRegistry functionRegistry = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - - Object userFunction = reactiveConsumer(); - - FunctionRegistration functionRegistration = new FunctionRegistration(userFunction, "reactiveConsumer") - .type(ResolvableType.forClassWithGenerics(Consumer.class, ResolvableType.forClassWithGenerics(Flux.class, Integer.class)).getType()); - functionRegistry.register(functionRegistration); - - FunctionInvocationWrapper functionWrapper = functionRegistry.lookup("reactiveConsumer"); - - functionWrapper.apply("123"); - } - - @Test - public void testHeaderEnricherFunction() { - FunctionRegistration registration = - new FunctionRegistration<>(new HeaderEnricherFunction(), "headerEnricher") - .type(HeaderEnricherFunction.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - Function, Message> function = catalog.lookup("headerEnricher"); - Message message = - function.apply(MessageBuilder.withPayload("hello").setHeader("original", "originalValue") - .build()); - assertThat(message.getHeaders().get("original")).isEqualTo("newValue"); - } - - @Test - public void testReactiveMonoSupplier() { - FunctionRegistration registration = new FunctionRegistration<>(new ReactiveMonoGreeter(), - "greeter").type(ReactiveMonoGreeter.class); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - FunctionInvocationWrapper function = catalog.lookup("greeter"); - assertThat(FunctionTypeUtils.isMono(function.getOutputType())); - } - - @Test - public void testFunctionCompositionWithReactiveSupplierAndConsumer() { - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - - Object reactiveFunc = reactiveFluxSupplier(); - FunctionRegistration functionRegistration = new FunctionRegistration(reactiveFunc, "reactiveFluxSupplier") - .type(ResolvableType.forClassWithGenerics( - Supplier.class, ResolvableType.forClassWithGenerics(Flux.class, String.class)).getType()); - catalog.register(functionRegistration); - - reactiveFunc = reactiveFluxConsumer(); - functionRegistration = new FunctionRegistration(reactiveFunc, "reactiveFluxConsumer") - .type(ResolvableType.forClassWithGenerics( - Consumer.class, ResolvableType.forClassWithGenerics(Flux.class, String.class)).getType()); - catalog.register(functionRegistration); - - FunctionInvocationWrapper lookedUpFunction = catalog - .lookup("reactiveFluxSupplier|reactiveFluxConsumer"); - - assertThat(lookedUpFunction).isNotNull(); - lookedUpFunction.apply(null); - assertThat(consumerDowncounter.get()).isZero(); - } - - @Test - void biConsumerUserFunctionTypeIsKnownInFunctionInvocationWrapper() { - BiConsumer testBiConsumer = (a, b) -> { }; - Function wrappedFunction = x -> { - testBiConsumer.accept(null, null); - return null; - }; - FunctionRegistration> registration = new FunctionRegistration<>( - wrappedFunction, "functionWrappingBiConsumer").type(Function.class); - registration.setUserFunction(testBiConsumer); - SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, - new JacksonMapper(new ObjectMapper())); - catalog.register(registration); - - FunctionInvocationWrapper functionInvocationWrapper = catalog.lookup("functionWrappingBiConsumer"); - - assertThat(functionInvocationWrapper.isWrappedBiConsumer()).isTrue(); - } - - public Function uppercase() { - return v -> v.toUpperCase(); - } - - - public Function hash() { - return v -> v.hashCode(); - } - - public Supplier supplier() { - return () -> 4; - } - - public Consumer consumer() { - return System.out::println; - } - - public Consumer> reactiveConsumer() { - return flux -> flux.subscribe(v -> { - System.out.println(v); - }); - } - - private final AtomicInteger consumerDowncounter = new AtomicInteger(10); - - public Supplier> reactiveFluxSupplier() { - return () -> Flux.fromStream( - IntStream.range(0, consumerDowncounter.get()).boxed().map(i -> Integer.toString(i)) - ); - } - - public Consumer> reactiveFluxConsumer() { - return flux -> flux.subscribe(v -> consumerDowncounter.decrementAndGet()); - } - - private FunctionCatalog configureCatalog(Class... configClass) { - ApplicationContext context = new SpringApplicationBuilder(configClass) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - @EnableAutoConfiguration - private static class CustomConverterConfiguration { - @Bean - public MessageConverter stringToPersonConverter() { - return new AbstractMessageConverter(MimeType.valueOf("text/person")) { - @Override - protected Object convertFromInternal(Message message, Class targetClass, @Nullable Object conversionHint) { - String payload = message.getPayload() instanceof byte[] ? new String((byte[]) message.getPayload()) : (String) message.getPayload(); - Person person = new Person(); - person.setName(payload); - return person; - } - - @Override - protected boolean canConvertFrom(Message message, @Nullable Class targetClass) { - return supportsMimeType(message.getHeaders()) && Person.class.isAssignableFrom(targetClass) && ( - message.getPayload() instanceof String || message.getPayload() instanceof byte[]); - } - - @Override - public Object convertToInternal(Object rawPayload, MessageHeaders headers, Object conversionHint) { - return rawPayload.toString(); - } - - @Override - protected boolean canConvertTo(Object payload, @Nullable MessageHeaders headers) { - return true; - } - - @Override - protected boolean supports(Class clazz) { - throw new UnsupportedOperationException(); - } - }; - } - - @Bean - public Function func() { - return person -> person.getName(); - } - } - - public static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } - } - - private static class Words implements Supplier { - - @Override - public String get() { - return "hello"; - } - - } - - private static class UpperCase implements Function { - - @Override - public String apply(String t) { - return t.toUpperCase(); - } - - } - - private static class Echo implements Function { - - @Override - public Object apply(Object t) { - return t; - } - - } - - private static class UpperCaseMessage - implements Function, Message> { - - @Override - public Message apply(Message t) { - return MessageBuilder.withPayload(t.getPayload().toUpperCase()) - .copyHeaders(t.getHeaders()).build(); - } - - } - - private static class Reverse implements Function { - - @Override - public String apply(String t) { - return new StringBuilder(t).reverse().toString(); - } - - } - - private static class ReverseMessage - implements Function, Message> { - - @Override - public Message apply(Message t) { - return MessageBuilder - .withPayload(new StringBuilder(t.getPayload()).reverse().toString()) - .copyHeaders(t.getHeaders()).build(); - } - - } - - private static class TestFunction implements Function { - - @Override - public String apply(Integer t) { - return "i=" + t; - } - - } - - private static class ReactiveFunction implements Function>>, Flux>> { - - @Override - public Flux> apply(Flux>> listFlux) { - return listFlux - .map(Message::getPayload) - .map(lst -> lst.stream().map(Person::getName).collect(Collectors.toList())); - } - } - - private static class ReactiveMonoGreeter implements Supplier>> { - - @Override - public Mono> get() { - return Mono.just(MessageBuilder.withPayload("hello").build()); - } - - } - - private static class HeaderEnricherFunction implements Function, Message> { - - @Override - public Message apply(Message message) { - return MessageBuilder.withPayload(message.getPayload()).setHeader("original", "newValue") - .build(); - } - } - - private static class StringArrayFunction implements Function { - @Override - public String apply(String[] t) { - return Arrays.asList(t).toString(); - } - } - - private static class StringListFunction implements Function, String> { - @Override - public String apply(List t) { - return t.toString(); - } - } - - private static class TypelessFunction implements Function { - @Override - public String apply(Object t) { - return t.toString(); - } - } - - private static class ByteArrayFunction implements Function { - @Override - public String apply(byte[] t) { - return new String(t); - } - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationConditionalLoadingTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationConditionalLoadingTests.java deleted file mode 100644 index 62b8d06fe..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationConditionalLoadingTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2022-2022 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.config; - -import io.cloudevents.spring.messaging.CloudEventMessageConverter; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.scan.TestFunction; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests the conditional loading aspects of the {@link ContextFunctionCatalogAutoConfiguration}. - * - * @author Chris Bono - */ -public class ContextFunctionCatalogAutoConfigurationConditionalLoadingTests { - - protected final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ContextFunctionCatalogAutoConfiguration.class)); - - @Test - void autoConfigDisabledWhenCustomFunctionCatalogExists() { - contextRunner.withBean(FunctionCatalog.class, () -> mock(FunctionCatalog.class)) - .run((context) -> assertThat(context).doesNotHaveBean(FunctionRegistry.class)); - } - - @Nested - class CloudEventsMessageConverterConfig { - - @Test - void cloudEventsMessageConverterBeanLoadedWhenCloudEventsOnClasspath() { - contextRunner.run((context) -> assertThat(context).hasSingleBean(CloudEventMessageConverter.class)); - } - - @Test - void cloudEventsMessageConverterBeanNotLoadedWhenCloudEventsNotOnClasspath() { - contextRunner.withClassLoader(new FilteredClassLoader(CloudEventMessageConverter.class)).run((context) -> - assertThat(context).doesNotHaveBean(CloudEventMessageConverter.class)); - } - - @Test - void customCloudEventsMessageConverterIsRespected() { - CloudEventMessageConverter customConverter = mock(CloudEventMessageConverter.class); - contextRunner.withBean(CloudEventMessageConverter.class, () -> customConverter) - .run((context) -> assertThat(context).getBean(CloudEventMessageConverter.class).isSameAs(customConverter)); - } - } - - @Nested - class PlainFunctionScanConfig { - - @Test - void functionScanConfigEnabledByDefault() { - contextRunner.withPropertyValues("spring.cloud.function.scan.packages:" + TestFunction.class.getPackageName()) - .run((context) -> assertThat(context).hasSingleBean(TestFunction.class)); - } - - @Test - void functionScanConfigEnabledWhenEnabledPropertySetToTrue() { - contextRunner.withPropertyValues("spring.cloud.function.scan.packages:" + TestFunction.class.getPackageName(), - "spring.cloud.function.scan.enabled:true") - .run((context) -> assertThat(context).hasSingleBean(TestFunction.class)); - } - - @Test - void functionScanConfigEnabledWithScanPackagesPointingToNoFunctions() { - contextRunner.withPropertyValues("spring.cloud.function.scan.packages:" + TestFunction.class.getPackageName() + ".faux", - "spring.cloud.function.scan.enabled:true") - .run((context) -> assertThat(context).doesNotHaveBean(TestFunction.class)); - } - - @Test - void functionScanConfigDisabledWhenEnabledPropertySetToFalse() { - contextRunner.withPropertyValues("spring.cloud.function.scan.packages:" + TestFunction.class.getPackageName(), - "spring.cloud.function.scan.enabled:false") - .run((context) -> assertThat(context).doesNotHaveBean(TestFunction.class)); - } - - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java deleted file mode 100644 index 6e4230b0d..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfigurationTests.java +++ /dev/null @@ -1,911 +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.config; - -import java.lang.reflect.Type; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -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.Disabled; -import org.junit.jupiter.api.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -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.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.inject.FooConfiguration; -import org.springframework.cloud.function.scan.ScannedFunction; -import org.springframework.cloud.function.test.GenericFunction; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.core.env.Environment; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.DescriptiveResource; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Artem Bilan - * @author Oleg Zhurakousky - * @author Anshul Mehra - */ -public class ContextFunctionCatalogAutoConfigurationTests { - - private ConfigurableApplicationContext context; - - private FunctionCatalog catalog; - - @AfterEach - public void close() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void lookUps() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")) - .isInstanceOf(Function.class); - assertThat(this.context.getBean("function2")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, - "function,function2")).isInstanceOf(Function.class); - Function, Flux> f = this.catalog.lookup(Function.class, - "function,function2,function3"); - assertThat(f).isInstanceOf(Function.class); - assertThat(f.apply(Flux.just("hello")).blockFirst()) - .isEqualTo("HELLOfunction2function3"); - assertThat(this.context.getBean("supplierFoo")).isInstanceOf(Supplier.class); - assertThat((Supplier) this.catalog.lookup(Supplier.class, "supplierFoo")) - .isInstanceOf(Supplier.class); - assertThat(this.context.getBean("supplier_Foo")).isInstanceOf(Supplier.class); - } - - @Test - // do we really need this test and behavior? What does this even mean? - public void ambiguousFunction() { - create(AmbiguousConfiguration.class); - assertThat(this.context.getBean("foos")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "foos")) - .isInstanceOf(Function.class); - assertThat((Supplier) this.catalog.lookup(Supplier.class, "foos")) - .isInstanceOf(Supplier.class); - Class inputType = ((FunctionInvocationWrapper) this.catalog.lookup(Function.class, "foos")).getRawInputType(); - assertThat(inputType).isEqualTo(String.class); - FunctionInvocationWrapper function = this.catalog.lookup("foos"); - Type outputType = function.getOutputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(outputType)).isEqualTo(Foo.class); - } - - @Test - public void configurationFunction() { - create(FunctionConfiguration.class); - assertThat(this.context.getBean("foos")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup(Function.class, "foos"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getGenericType(inputType)).isEqualTo(String.class); - Type outputType = function.getOutputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(outputType)).isEqualTo(Foo.class); - } - - @Test - public void dependencyInjection() { - create(DependencyInjectionConfiguration.class); - assertThat(this.context.getBean("foos")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "foos")) - .isInstanceOf(Function.class); - Class inputType = ((FunctionInvocationWrapper) this.catalog.lookup(Function.class, "foos")).getRawInputType(); - assertThat(inputType).isEqualTo(String.class); - } - - @Test - public void externalDependencyInjection() { - create(ExternalDependencyConfiguration.class); - assertThat(this.context.getBean("foos")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "foos")) - .isInstanceOf(Function.class); - Class inputType = ((FunctionInvocationWrapper) this.catalog.lookup(Function.class, "foos")).getRawInputType(); - assertThat(inputType).isEqualTo(String.class); - } - - @Test - public void composedFunction() { - create(MultipleConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup(Function.class, "foos"); - assertThat(function).isInstanceOf(Function.class); - - function = this.catalog.lookup(Function.class, "foos,bars"); - Class inputType = function.getRawInputType(); - assertThat(inputType).isAssignableFrom(String.class); - Class outputType = function.getRawOutputType(); - assertThat(outputType).isAssignableFrom(Bar.class); - } - - @Test - public void composedSupplier() { - create(MultipleConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup("names,foos"); - assertThat(function).isInstanceOf(Supplier.class); - assertThat(function.getRawOutputType()).isAssignableFrom(Foo.class); - assertThat(function.getRawInputType()).isNull(); - } - - @Test - public void composedConsumer() { - create(MultipleConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup("foos,print"); - assertThat(function).isInstanceOf(Consumer.class); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.getRawInputType()).isAssignableFrom(String.class); - assertThat(function.getRawOutputType()).isNull(); - } - - @Test - public void genericFunction() { - create(GenericConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.getRawInputType()).isAssignableFrom(Map.class); - } - - @Test - public void fluxMessageFunction() { - create(FluxMessageConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypeMessage()).isTrue(); - - final Type inputType = function.getInputType(); - - assertThat(FunctionTypeUtils.getRawType(inputType)).isAssignableFrom(Flux.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Message.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(FunctionTypeUtils.getGenericType(inputType)))).isAssignableFrom(String.class); - } - - @Test - public void publisherMessageFunction() { - create(PublisherMessageConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypeMessage()).isTrue(); - - final Type inputType = function.getInputType(); - - assertThat(FunctionTypeUtils.getRawType(inputType)).isAssignableFrom(Publisher.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Message.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(FunctionTypeUtils.getGenericType(inputType)))).isAssignableFrom(String.class); - - } - - @Test - public void monoFunction() { - create(MonoConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypeMessage()).isFalse(); - Type inputType = function.getInputType(); - Type outputType = function.getOutputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(String.class); - assertThat(FunctionTypeUtils.getRawType(inputType)).isAssignableFrom(Flux.class); - assertThat(FunctionTypeUtils.getRawType(outputType)).isAssignableFrom(Mono.class); - } - - @Test - public void monoToMonoNonVoidFunction() { - create(MonoToMonoNonVoidConfiguration.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(String.class); - Type outputType = function.getOutputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(outputType)).isAssignableFrom(String.class); - } - - @Test - public void messageFunction() { - create(MessageConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypeMessage()).isTrue(); - assertThat(function.isOutputTypeMessage()).isTrue(); - Type inputType = function.getInputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(String.class); - } - - @Test - public void genericFluxFunction() { - create(GenericFluxConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Map.class); - assertThat(FunctionTypeUtils.getRawType(inputType)).isAssignableFrom(Flux.class); - } - - @Test - public void externalFunction() { - create(ExternalConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Map.class); - } - - @Test - public void singletonFunction() { - create(SingletonConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypePublisher()).isFalse(); - assertThat(function.isOutputTypePublisher()).isFalse(); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Integer.class); - } - - @Test - @Disabled - public void singletonMessageFunction() { - create(SingletonMessageConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.isInputTypeMessage()).isTrue(); - Type inputType = function.getInputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(Integer.class); - } - - @Test - public void nonParametericTypeFunction() { - create(NonParametricTypeSingletonConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(Integer.class); - } - - @Test - public void componentScanBeanFunction() { - create(ComponentScanBeanConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Map.class); - } - - @Test - public void componentScanFunction() { - create(ComponentScanConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("function"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(inputType))).isAssignableFrom(Map.class); - } - - @Test - public void componentScanJarFunction() { - try { - create("greeter.jar", ComponentScanJarConfiguration.class); - assertThat(this.context.getBean("greeter")).isInstanceOf(Function.class); - FunctionInvocationWrapper function = this.catalog.lookup("greeter"); - assertThat(function).isInstanceOf(Function.class); - Type inputType = function.getInputType(); - assertThat((Class) FunctionTypeUtils.getGenericType(inputType)).isAssignableFrom(String.class); - } - finally { - ClassUtils.overrideThreadContextClassLoader(getClass().getClassLoader()); - } - } - - private void create(String jarfile, Class config, String... props) { - try { - URL[] urls = new URL[] { new ClassPathResource(jarfile).getURL() }; - ClassUtils.overrideThreadContextClassLoader( - new URLClassLoader(urls, getClass().getClassLoader())); - create(config, props); - } - catch (Exception e) { - ReflectionUtils.rethrowRuntimeException(e); - } - } - - @Test - public void simpleFunction() { - create(SimpleConfiguration.class); - Object bean = this.context.getBean("function"); - assertThat(bean).isInstanceOf(Function.class); - Function, Flux> function = this.catalog - .lookup(Function.class, "function"); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - assertThat(bean).isNotSameAs(function); - } - - @Test - @Disabled - public void simpleSupplier() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("supplier")).isInstanceOf(Supplier.class); - Supplier> supplier = this.catalog.lookup(Supplier.class, "supplier"); - assertThat(supplier.get().blockFirst()).isEqualTo("hello"); - } - - @Test - public void simpleConsumer() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("consumer")).isInstanceOf(Consumer.class); - Function, Mono> consumer = this.catalog.lookup(Function.class, - "consumer"); - consumer.apply(Flux.just("foo", "bar")).subscribe(); - assertThat(this.context.getBean(SimpleConfiguration.class).list).hasSize(2); - } - - @Test - @Disabled - public void qualifiedBean() { - create(QualifiedConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup("function")).isNull(); - assertThat((Function) this.catalog.lookup("other")).isNotNull(); - assertThat(FunctionTypeUtils.getGenericType(((FunctionInvocationWrapper) this.catalog.lookup("other")).getInputType())) - .isEqualTo(String.class); - } - - @Test - public void aliasBean() { - create(AliasConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")) - .isNotNull(); - assertThat((Function) this.catalog.lookup(Function.class, "other")) - .isInstanceOf(Function.class); - } - - @Test - @Disabled - public void registrationBean() { - create(RegistrationConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "registration")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "other")) - .isInstanceOf(Function.class); - } - - @Test - public void factoryBeanFunction() { - create(FactoryBeanConfiguration.class); - assertThat(this.context.getBean("function")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")) - .isInstanceOf(Function.class); - Function, Flux> f = this.catalog.lookup(Function.class, - "function"); - assertThat(f.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO-bar"); - } - - @Test - public void functionCatalogDependentBeanFactoryPostProcessor() { - create(new Class[]{ComponentFunctionConfiguration.class, AppendFunction.class}); - assertThat(this.context.getBean("appendFunction")).isInstanceOf(Function.class); - assertThat((Function) this.catalog.lookup(Function.class, "appendFunction")) - .isInstanceOf(Function.class); - Function, Flux> f = this.catalog.lookup(Function.class, - "appendFunction"); - assertThat(f.apply(Flux.just("World")).blockFirst()).isEqualTo("Hello World"); - } - - private void create(Class type, String... props) { - create(new Class[] { type }, props); - } - - private void create(Class[] types, String... props) { - this.context = new SpringApplicationBuilder(types).properties(props).run(); - this.catalog = this.context.getBean(FunctionCatalog.class); -// this.inspector = this.context.getBean(FunctionInspector.class); - } - - @EnableAutoConfiguration - @Configuration - protected static class EmptyConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - protected static class SimpleConfiguration { - - private List list = new ArrayList<>(); - - @Bean - public Function function() { - return value -> value.toUpperCase(); - } - - @Bean - public Function function2() { - return value -> value + "function2"; - } - - @Bean - public Function function3() { - return value -> value + "function3"; - } - - @Bean - public Supplier supplier() { - return () -> "hello"; - } - - @Bean(name = { "supplierFoo", "supplier_Foo" }) - public Supplier foo() { - return () -> "hello"; - } - - @Bean - public Consumer consumer() { - return value -> { - this.list.add(value); - }; - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class ComponentFunctionConfiguration { - @Bean - public String value() { - return "Hello "; - } - - @Bean - public BeanFactoryPostProcessor someBeanFactoryPostProcessor(Environment environment, - @Nullable FunctionRegistry functionCatalog) { - return beanFactory -> { }; - } - } - - @Component("appendFunction") - public static class AppendFunction implements Function { - private String value; - - public AppendFunction(String value) { - this.value = value; - } - - @Override - public String apply(String s) { - return this.value + s; - } - } - - @EnableAutoConfiguration - @Configuration - protected static class DependencyInjectionConfiguration { - - @Bean - public Function foos(String foo) { - return value -> new Foo(foo + ": " + value.toUpperCase()); - } - - @Bean - public String value() { - return "Hello"; - } - - } - - @EnableAutoConfiguration - @Configuration("foos") - protected static class FunctionConfiguration - implements Function, Flux> { - - @Override - public Flux apply(Flux flux) { - return flux.map(foo -> new Foo(value() + ": " + foo.toUpperCase())); - } - - @Bean - public String value() { - return "Hello"; - } - - } - - @EnableAutoConfiguration - @Configuration - @ComponentScan(basePackageClasses = FooConfiguration.class) - protected static class ExternalDependencyConfiguration { - - @Bean - public String value() { - return "Hello"; - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class AmbiguousConfiguration { - - @Bean - public Function foos() { - return value -> new Foo(value.toUpperCase()); - } - - @Bean - @Qualifier("foos") - public Supplier supplier() { - return () -> new Foo("bar"); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class MultipleConfiguration { - - @Bean - public Function foos() { - return value -> new Foo(value.toUpperCase()); - } - - @Bean - public Function bars() { - return value -> new Bar(value.getValue()); - } - - @Bean - public Consumer print() { - return System.out::println; - } - - @Bean - public Supplier names() { - return () -> "Mark"; - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class GenericConfiguration { - - @Bean - public Function, Map> function() { - return m -> m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), - e -> e.getValue().toString().toUpperCase())); - } - - } - - @EnableAutoConfiguration - @Configuration - @Import(GenericFunction.class) - protected static class ExternalConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - protected static class SingletonConfiguration implements BeanFactoryPostProcessor { - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { - beanFactory.registerSingleton("function", new SingletonFunction()); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class SingletonMessageConfiguration - implements BeanFactoryPostProcessor { - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { - beanFactory.registerSingleton("function", new SingletonMessageFunction()); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class NonParametricTypeSingletonConfiguration { - - @Bean - public SingletonFunction function() { - return new SingletonFunction(); - } - - } - - protected static class SingletonFunction implements Function { - - @Override - public String apply(Integer input) { - return "value=" + input; - } - - } - - protected static class SingletonMessageFunction - implements Function, Message> { - - @Override - public Message apply(Message input) { - return MessageBuilder.withPayload("value=" + input.getPayload()).build(); - } - - } - - @EnableAutoConfiguration - @Configuration - @ComponentScan(basePackageClasses = GenericFunction.class) - protected static class ComponentScanBeanConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - @ComponentScan(basePackageClasses = ScannedFunction.class) - protected static class ComponentScanConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - protected static class ComponentScanJarConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - protected static class GenericFluxConfiguration { - - @Bean - public Function>, Flux>> function() { - return flux -> flux.map(m -> m.entrySet().stream().collect(Collectors - .toMap(e -> e.getKey(), e -> e.getValue().toString().toUpperCase()))); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class FluxMessageConfiguration { - - @Bean - public Function>, Flux>> function() { - return flux -> flux.map(m -> MessageBuilder - .withPayload(m.getPayload().toUpperCase()).build()); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class PublisherMessageConfiguration { - - @Bean - public Function>, Publisher>> function() { - return flux -> Flux.from(flux).map(m -> MessageBuilder - .withPayload(m.getPayload().toUpperCase()).build()); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class MonoConfiguration { - - @Bean - public Function, Mono>> function() { - return flux -> flux.collect(HashMap::new, - (map, word) -> map.merge(word, 1, Integer::sum)); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class MonoToMonoNonVoidConfiguration { - - @Bean - public Function, Mono> function() { - return mono -> mono; - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class MessageConfiguration { - - @Bean - public Function, Message> function() { - return m -> MessageBuilder.withPayload(m.getPayload().toUpperCase()).build(); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class QualifiedConfiguration { - - @Bean - @Qualifier("other") - public Function function() { - return value -> value.toUpperCase(); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class AliasConfiguration { - - @Bean({ "function", "other" }) - public Function function() { - return value -> value.toUpperCase(); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class RegistrationConfiguration { - - @Bean - public FunctionRegistration> registration() { - return new FunctionRegistration>(function(), - "other"); - } - - @Bean - public Function function() { - return value -> value.toUpperCase(); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class FactoryBeanConfiguration - implements BeanDefinitionRegistryPostProcessor { - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) - throws BeansException { - RootBeanDefinition beanDefinition = new RootBeanDefinition( - FunctionFactoryBean.class); - beanDefinition.setSource(new DescriptiveResource("Function")); - registry.registerBeanDefinition("function", beanDefinition); - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { - - } - - } - - private static class FunctionFactoryBean - extends AbstractFactoryBean> { - - @Override - public Class getObjectType() { - return Function.class; - } - - @Override - protected Function createInstance() throws Exception { - return s -> s.toUpperCase() + "-bar"; - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - public static class Bar { - - private String message; - - public Bar(String value) { - this.message = value; - } - - Bar() { - } - - public String getMessage() { - return this.message; - } - - public void setMessage(String message) { - this.message = message; - } - - } - -} 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 deleted file mode 100644 index 3b3075a73..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializerTests.java +++ /dev/null @@ -1,428 +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.config; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import com.google.gson.Gson; -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 reactor.core.publisher.Mono; - -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.BeanCreationException; -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.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.scan.TestFunction; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.MapPropertySource; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class ContextFunctionCatalogInitializerTests { - - private GenericApplicationContext context; - - private FunctionCatalog catalog; - - @AfterEach - public void close() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void lookUps() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("function")) - .isInstanceOf(FunctionRegistration.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")) - .isInstanceOf(Function.class); - } - - @Test - public void properties() { - create(PropertiesConfiguration.class, "app.greeting=hello"); - assertThat(this.context.getBean("function")) - .isInstanceOf(FunctionRegistration.class); - @SuppressWarnings("unchecked") - Function, Flux> function = (Function, Flux>) this.catalog - .lookup(Function.class, "function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo"); - } - - @Test - public void value() { - create(ValueConfiguration.class, "app.greeting=hello"); - assertThat(this.context.getBean("function")) - .isInstanceOf(FunctionRegistration.class); - @SuppressWarnings("unchecked") - Function, Flux> function = (Function, Flux>) this.catalog - .lookup(Function.class, "function"); - assertThat(function).isInstanceOf(Function.class); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo"); - } - - @Test - @Disabled - public void compose() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("function")) - .isInstanceOf(FunctionRegistration.class); - @SuppressWarnings("unchecked") - Supplier> supplier = (Supplier>) this.catalog - .lookup(Supplier.class, "supplier|function"); - assertThat(supplier).isInstanceOf(Supplier.class); - assertThat(supplier.get().blockFirst()).isEqualTo("HELLO"); - // TODO: support for function composition - } - - @Test - public void missingType() { - Assertions.assertThrows(BeanCreationException.class, () -> { - create(MissingTypeConfiguration.class); - assertThat(this.context.getBean("function")) - .isInstanceOf(FunctionRegistration.class); - assertThat((Function) this.catalog.lookup(Function.class, "function")) - .isInstanceOf(Function.class); - // TODO: support for type inference from functional bean registrations - }); - } - - @Test - public void dependencyInjection() { - create(DependencyInjectionConfiguration.class); - assertThat(this.context.getBean("foos")).isInstanceOf(FunctionRegistration.class); - assertThat((Function) this.catalog.lookup(Function.class, "foos")) - .isInstanceOf(Function.class); - } - - @Test - public void simpleFunction() { - create(SimpleConfiguration.class); - Object bean = this.context.getBean("function"); - assertThat(bean).isInstanceOf(FunctionRegistration.class); - Function, Flux> function - = this.catalog.lookup(Function.class, "function"); - assertThat(function.apply(Flux.just("{\"name\":\"foo\"}")).blockFirst().getName()).isEqualTo("FOO"); - assertThat(bean).isNotSameAs(function); - } - - @Test - public void scanFunction() { - create(EmptyConfiguration.class, - "spring.cloud.function.scan.packages=org.springframework.cloud.function.context.scan"); - Object bean = this.context.getBean(TestFunction.class.getName()); - assertThat(bean).isInstanceOf(Function.class); - Function, Flux> function = this.catalog - .lookup(Function.class, TestFunction.class.getName()); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - assertThat(bean).isNotSameAs(function); - } - - @Test - public void simpleSupplier() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("supplier")) - .isInstanceOf(FunctionRegistration.class); - Supplier supplier = this.catalog.lookup(Supplier.class, "supplier"); - assertThat(supplier.get()).isEqualTo("hello"); - } - - @Test - public void simpleConsumer() { - create(SimpleConfiguration.class); - assertThat(this.context.getBean("consumer")) - .isInstanceOf(FunctionRegistration.class); - Function, Mono> consumer = this.catalog.lookup(Function.class, - "consumer"); - consumer.apply(Flux.just("foo", "bar")).subscribe(); - assertThat(this.context.getBean(SimpleConfiguration.class).list).hasSize(2); - } - - @Test - public void overrideGson() { - create(GsonConfiguration.class); - Gson user = this.context.getBean(GsonConfiguration.class).gson(); - Gson bean = this.context.getBean(Gson.class); - assertThat(user).isSameAs(bean); - } - - @SuppressWarnings("unchecked") - private void create( - Class> type, - String... props) { - create(Arrays.asList(BeanUtils.instantiateClass(type)) - .toArray(new ApplicationContextInitializer[0]), props); - } - - private void create(ApplicationContextInitializer[] types, - String... props) { - this.context = new GenericApplicationContext(); - Map map = new HashMap<>(); - for (String prop : props) { - String[] array = StringUtils.delimitedListToStringArray(prop, "="); - String key = array[0]; - String value = array.length > 1 ? array[1] : ""; - map.put(key, value); - } - if (!map.isEmpty()) { - this.context.getEnvironment().getPropertySources() - .addFirst(new MapPropertySource("testProperties", map)); - } - for (ApplicationContextInitializer type : types) { - type.initialize(this.context); - } - new ContextFunctionCatalogInitializer.ContextFunctionCatalogBeanRegistrar( - this.context).postProcessBeanDefinitionRegistry(this.context); - this.context.refresh(); - this.catalog = this.context.getBean(FunctionCatalog.class); - } - - protected static class EmptyConfiguration - implements ApplicationContextInitializer { - - @Override - public void initialize(GenericApplicationContext applicationContext) { - } - - } - - protected static class MissingTypeConfiguration - implements ApplicationContextInitializer { - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function())); - } - - @Bean - public Function function() { - return value -> value.toUpperCase(); - } - - } - - protected static class SimpleConfiguration - implements ApplicationContextInitializer { - - private List list = new ArrayList<>(); - - - @Override - public void initialize(GenericApplicationContext context) { - - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(Person.class, Person.class))); - context.registerBean("supplier", FunctionRegistration.class, - () -> new FunctionRegistration<>(supplier()) - .type(FunctionTypeUtils.supplierType(String.class))); - context.registerBean("consumer", FunctionRegistration.class, - () -> new FunctionRegistration<>(consumer()) - .type(FunctionTypeUtils.consumerType(String.class))); - context.registerBean(SimpleConfiguration.class, () -> this); - } - - @Bean - public Function function() { - return person -> { - Person p = new Person(); - p.setName(person.getName().toUpperCase()); - return p; - }; - } - - @Bean - public Supplier supplier() { - return () -> "hello"; - } - - @Bean - public Consumer consumer() { - return value -> this.list.add(value); - } - } - - @ConfigurationProperties("app") - protected static class PropertiesConfiguration - implements ApplicationContextInitializer { - - private String greeting; - - public String getGreeting() { - return this.greeting; - } - - public void setGreeting(String greeting) { - this.greeting = greeting; - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(String.class, String.class))); - context.registerBean(PropertiesConfiguration.class, () -> this); - } - - @Bean - public Function function() { - return value -> this.greeting + " " + value; - } - - } - - protected static class ValueConfiguration - implements ApplicationContextInitializer { - - @Value("${app.greeting}") - private String greeting; - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(function()).type(FunctionTypeUtils.functionType(String.class, String.class))); - context.registerBean(ValueConfiguration.class, () -> this); - } - - @Bean - public Function function() { - return value -> this.greeting + " " + value; - } - - } - - protected static class GsonConfiguration - implements ApplicationContextInitializer { - - private Gson gson = new Gson(); - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("gson", Gson.class, this::gson); - context.registerBean(GsonConfiguration.class, () -> this); - } - - @Bean - public Gson gson() { - return this.gson; - } - - } - - protected static class DependencyInjectionConfiguration - implements ApplicationContextInitializer { - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean(String.class, () -> value()); - context.registerBean("foos", FunctionRegistration.class, - () -> new FunctionRegistration<>(foos(context.getBean(String.class))) - .type(FunctionTypeUtils.functionType(String.class, Foo.class))); - } - - @Bean - public Function foos(String foo) { - return value -> new Foo(foo + ": " + value.toUpperCase()); - } - - @Bean - public String value() { - return "Hello"; - } - - } - - protected static class FunctionConfiguration - implements Function, Flux>, - ApplicationContextInitializer { - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("foos", FunctionConfiguration.class, () -> this); - context.registerBean("function", FunctionRegistration.class, - () -> new FunctionRegistration<>(this, "foos") - .type(FunctionConfiguration.class)); - } - - @Override - public Flux apply(Flux flux) { - return flux.map(foo -> new Foo(value() + ": " + foo.toUpperCase())); - } - - @Bean - public String value() { - return "Hello"; - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - - private static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/JsonMessageConverterTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/JsonMessageConverterTests.java deleted file mode 100644 index 5af30522e..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/JsonMessageConverterTests.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2023-2023 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.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class JsonMessageConverterTests { - - @Test - public void testTypeInference() { - JsonMessageConverter converter = new JsonMessageConverter(new JacksonMapper(new ObjectMapper())); - - Message message = MessageBuilder.withPayload("{\"name\":\"bill\"}").build(); - assertThat(converter.canConvertFrom(message, Person.class)).isTrue(); - - message = MessageBuilder.withPayload("{\"name\":\"bill\"}").setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON).build(); - assertThat(converter.canConvertFrom(message, Person.class)).isTrue(); - assertThat(converter.canConvertFrom(message, Object.class)).isFalse(); - assertThat(converter.canConvertFrom(message, null)).isFalse(); - assertThat(converter.convertFromInternal(message, Person.class, null)).isInstanceOf(Person.class); - - message = MessageBuilder.withPayload("{\"name\":\"bill\"}") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON.toString() + ";type=" + Person.class.getName()).build(); - assertThat(converter.canConvertFrom(message, Object.class)).isTrue(); - assertThat(converter.canConvertFrom(message, null)).isTrue(); - assertThat(converter.convertFromInternal(message, Person.class, null)).isInstanceOf(Person.class); - assertThat(converter.convertFromInternal(message, Object.class, null)).isInstanceOf(Person.class); - assertThat(converter.convertFromInternal(message, null, null)).isInstanceOf(Person.class); - } - - public static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java deleted file mode 100644 index 591d60b09..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/config/RoutingFunctionTests.java +++ /dev/null @@ -1,331 +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.config; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.DefaultMessageRoutingHandler; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class RoutingFunctionTests { - - private ConfigurableApplicationContext context; - - @AfterEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - System.clearProperty("spring.cloud.function.routing-expression"); - context.close(); - } - - private FunctionCatalog configureCatalog(Class configurationClass) { - context = new SpringApplicationBuilder(configurationClass).run( - "--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.routing.enabled=true"); - return context.getBean(FunctionCatalog.class); - } - - private FunctionCatalog configureCatalog() { - return configureCatalog(RoutingFunctionConfiguration.class); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testDefaultRouting() { - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "blah").build(); - - FunctionCatalog functionCatalog = this.configureCatalog(EmptyConfiguration.class); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - try { - function.apply(message); - fail(); - } - catch (Exception e) { - // Good - } - // - functionCatalog = this.configureCatalog(ConfigurationWithDefaultMessageRoutingHandler.class); - function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - function.apply(message); - ConfigurationWithDefaultMessageRoutingHandler config = this.context.getBean(ConfigurationWithDefaultMessageRoutingHandler.class); - assertThat(config.defaultHandlerInvoked).isTrue(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testInvocationWithMessageAndHeader() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "reverse").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testRoutingSimpleInputWithReactiveFunctionWithMessageHeader() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "echoFlux").build(); - assertThat(((Flux) function.apply(message)).blockFirst()).isEqualTo("hello"); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testRoutingReactiveInputWithReactiveFunctionAndDefinitionMessageHeader() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "echoFlux").build(); - Flux resultFlux = (Flux) function.apply(Flux.just(message)); - - StepVerifier.create(resultFlux).expectError().verify(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testRoutingReactiveInputWithReactiveFunctionAndExpressionMessageHeader() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".routing-expression", "'echoFlux'").build(); - Flux resultFlux = (Flux) function.apply(Flux.just(message)); - StepVerifier.create(resultFlux).expectError().verify(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void failWithHeaderProvidedExpressionAccessingRuntime() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".routing-expression", - "T(java.lang.Runtime).getRuntime().exec(\"open -a calculator.app\")") - .build(); - try { - function.apply(message); - fail(); - } - catch (Exception e) { - assertThat(e.getMessage()).isEqualTo("EL1005E: Type cannot be found 'java.lang.Runtime'"); - } - - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testInvocationWithMessageAndDefinitionProperty() { - System.setProperty(FunctionProperties.PREFIX + ".definition", "reverse"); - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testInvocationWithMessageAndRoutingExpression() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "headers.function_name"); - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").setHeader("function_name", "reverse").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test - public void testInvocationWithMessageAndRoutingExpressionCaseInsensitive() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "headers.function_Name"); - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").setHeader("function_name", "reverse").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); - - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "headers.FunCtion_namE"); - assertThat(function.apply(message)).isEqualTo("olleh"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testInvocationWithRoutingBeanExpression() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", - "@reverse.apply(#root.getHeaders().get('func'))"); - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").setHeader("func", "esacreppu").build(); - assertThat(function.apply(message)).isEqualTo("HELLO"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testOtherExpectedFailures() { - FunctionCatalog functionCatalog = this.configureCatalog(); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - // no function.definition header or function property - try { - function.apply(MessageBuilder.withPayload("hello").build()); - Assertions.fail(); - } - catch (Exception e) { - // ignore - } - - // non existing function - try { - function.apply(MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "blah").build()); - Assertions.fail(); - } - catch (Exception e) { - // ignore - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testInvocationWithMessageComposed() { - FunctionCatalog functionCatalog = this.configureCatalog(); - - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME + "|reverse"); - assertThat(function).isNotNull(); - - Message message = MessageBuilder.withPayload("hello") - .setHeader(FunctionProperties.PREFIX + ".definition", "uppercase").build(); - - assertThat(function.apply(message)).isEqualTo("OLLEH"); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testMultipleRouters() { - System.setProperty(FunctionProperties.PREFIX + ".routing-expression", "'uppercase'"); - FunctionCatalog functionCatalog = this.configureCatalog(MultipleRouterConfiguration.class); - Function function = functionCatalog.lookup(RoutingFunction.FUNCTION_NAME); - assertThat(function).isNotNull(); - Message message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("HELLO"); - - function = functionCatalog.lookup("mySpecialRouter"); - assertThat(function).isNotNull(); - message = MessageBuilder.withPayload("hello").build(); - assertThat(function.apply(message)).isEqualTo("olleh"); - } - - @EnableAutoConfiguration - @Configuration - protected static class RoutingFunctionConfiguration { - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function uppercase() { - return String::toUpperCase; - } - - @Bean - public Function, Flux> echoFlux() { - return f -> f; - } - } - - @EnableAutoConfiguration - @Configuration - protected static class MultipleRouterConfiguration { - - @Bean - RoutingFunction mySpecialRouter(FunctionCatalog functionCatalog, BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) { - Map propertiesMap = new HashMap<>(); - propertiesMap.put(FunctionProperties.PREFIX + ".routing-expression", "'reverse'"); - return new RoutingFunction(functionCatalog, propertiesMap, new BeanFactoryResolver(beanFactory), routingCallback); - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function uppercase() { - return String::toUpperCase; - } - } - - @EnableAutoConfiguration - @Configuration - protected static class EmptyConfiguration { - } - - @EnableAutoConfiguration - @Configuration - protected static class ConfigurationWithDefaultMessageRoutingHandler { - public boolean defaultHandlerInvoked; - @Bean - public DefaultMessageRoutingHandler defaultRoutingHandler() { - return new DefaultMessageRoutingHandler() { - @Override - public void accept(Message message) { - super.accept(message); - defaultHandlerInvoked = true; - } - }; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/scan/TestFunction.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/scan/TestFunction.java deleted file mode 100644 index ad12ee4b9..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/scan/TestFunction.java +++ /dev/null @@ -1,32 +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.scan; - -import java.util.function.Function; - -/** - * @author Dave Syer - * - */ -public class TestFunction implements Function { - - @Override - public String apply(String t) { - return t.toUpperCase(); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/string/FunctionalStringSourceTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/string/FunctionalStringSourceTests.java deleted file mode 100644 index 585e2043a..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/string/FunctionalStringSourceTests.java +++ /dev/null @@ -1,60 +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.string; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test that spring.main.sources works with the functional approach. - * - * @author Dave Syer - * - */ -// @checkstyle:off -@FunctionalSpringBootTest(classes = Object.class, properties = "spring.main.sources=org.springframework.cloud.function.context.string.FunctionalStringSourceTests.TestConfiguration") -// @checkstyle:on -public class FunctionalStringSourceTests { - - @Autowired - private FunctionCatalog catalog; - - @Test - public void words() throws Exception { - Function, Flux> function = this.catalog - .lookup(Function.class, "function"); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - } - - protected static class TestConfiguration implements Function { - - @Override - public String apply(String value) { - return value.toUpperCase(); - } - - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/test/FunctionalTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/test/FunctionalTests.java deleted file mode 100644 index a22958732..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/test/FunctionalTests.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.context.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.cloud.function.context.FunctionCatalog; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@FunctionalSpringBootTest -public class FunctionalTests { - - @Autowired - private FunctionCatalog catalog; - - @Test - public void words() throws Exception { - Function, Flux> function = this.catalog - .lookup(Function.class, "function"); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - } - - @SpringBootConfiguration - protected static class TestConfiguration implements Function { - - @Override - public String apply(String value) { - return value.toUpperCase(); - } - - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/inject/FooConfiguration.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/inject/FooConfiguration.java deleted file mode 100644 index e7db39122..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/inject/FooConfiguration.java +++ /dev/null @@ -1,33 +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.inject; - -import java.util.function.Function; - -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfigurationTests.Foo; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class FooConfiguration { - - @Bean - public Function foos(String foo) { - return value -> new Foo(foo + ": " + value.toUpperCase()); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/scan/ScannedFunction.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/scan/ScannedFunction.java deleted file mode 100644 index 83f49d38d..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/scan/ScannedFunction.java +++ /dev/null @@ -1,39 +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.scan; - -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.springframework.stereotype.Component; - -/** - * @author Dave Syer - * - */ -@Component("function") -public class ScannedFunction - implements Function, Map> { - - @Override - public Map apply(Map m) { - return m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), - e -> e.getValue().toString().toUpperCase())); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/test/GenericFunction.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/test/GenericFunction.java deleted file mode 100644 index 46ae2b9d4..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/test/GenericFunction.java +++ /dev/null @@ -1,39 +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.test; - -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Dave Syer - * - */ -@Configuration -public class GenericFunction { - - @Bean - public Function, Map> function() { - return m -> m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), - e -> e.getValue().toString().toUpperCase())); - } - -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/userissues/UserIssuesTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/userissues/UserIssuesTests.java deleted file mode 100644 index 7a2b7c533..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/userissues/UserIssuesTests.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2020-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.userissues; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.ResolvableType; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.GenericMessage; - - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * - */ -public class UserIssuesTests { - - private FunctionCatalog configureCatalog(Class... configClass) { - ApplicationContext context = new SpringApplicationBuilder(configClass).run( - "--logging.level.org.springframework.cloud.function=DEBUG", "--spring.main.lazy-initialization=true"); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - return catalog; - } - - @BeforeEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - } - - @Test - public void testIssue602() throws Exception { - FunctionCatalog catalog = this.configureCatalog(Issue602Configuration.class); - Function, Integer> function = catalog.lookup("consumer"); - int result = function.apply( - new GenericMessage("[{\"name\":\"julien\"},{\"name\":\"ricky\"},{\"name\":\"bubbles\"}]")); - assertThat(result).isEqualTo(3); - } - - @Test - public void testIssue602asPOJO() throws Exception { - FunctionCatalog catalog = this.configureCatalog(Issue602Configuration.class); - Function>, Integer> function = catalog.lookup("consumer"); - ArrayList products = new ArrayList<>(); - Product p = new Product(); - p.setName("julien"); - products.add(p); - p = new Product(); - p.setName("ricky"); - products.add(p); - p = new Product(); - p.setName("bubbles"); - products.add(p); - int result = function.apply(new GenericMessage>(products)); - assertThat(result).isEqualTo(3); - - } - - @Test - public void testIssue602asCollectionOfUnconvertedItems() throws Exception { - FunctionCatalog catalog = this.configureCatalog(Issue602Configuration.class); - Function>, Integer> function = catalog.lookup("consumer"); - ArrayList products = new ArrayList<>(); - products.add("{\"name\":\"julien\"}"); - products.add("{\"name\":\"ricky\"}"); - products.add("{\"name\":\"bubbles\"}"); - int result = function.apply(new GenericMessage>(products)); - assertThat(result).isEqualTo(3); - - } - - @SuppressWarnings("unchecked") - @Test - public void testIssue601() throws Exception { - FunctionCatalog catalog = this.configureCatalog(Issue601Configuration.class); - FunctionInvocationWrapper function = catalog.lookup("uppercase"); - assertThat(function.getInputType().getTypeName()) - .isEqualTo(ResolvableType.forClassWithGenerics(Flux.class, String.class).getType().getTypeName()); - assertThat(function.getOutputType().getTypeName()) - .isEqualTo(ResolvableType.forClassWithGenerics(Flux.class, Integer.class).getType().getTypeName()); - Flux result = (Flux) function.apply(Flux.just("julien", "ricky", "bubbles")); - List results = result.collectList().block(); - assertThat(results.get(0)).isEqualTo(6); - assertThat(results.get(1)).isEqualTo(5); - assertThat(results.get(2)).isEqualTo(7); - } - - @EnableAutoConfiguration - @Configuration - public static class Issue602Configuration { - @Bean - public Function, Integer> consumer() { - return v -> { - assertThat(v.get(0).getName()).isEqualTo("julien"); - assertThat(v.get(1).getName()).isEqualTo("ricky"); - assertThat(v.get(2).getName()).isEqualTo("bubbles"); - return v.size(); - }; - } - } - - @EnableAutoConfiguration - @Configuration - public static class Issue601Configuration { - @Bean - public Uppercase uppercase() { - return new Uppercase(); - } - } - - public static class Uppercase implements Function, Flux> { - - @Override - public Flux apply(Flux s) { - return s.map(v -> v.length()); - } - } - - public static class Product { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java b/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java deleted file mode 100644 index 30207d367..000000000 --- a/spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java +++ /dev/null @@ -1,143 +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.utils; - -import java.util.List; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.gson.Gson; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import org.springframework.cloud.function.json.GsonMapper; -import org.springframework.cloud.function.json.JacksonMapper; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.core.ResolvableType; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -public class JsonMapperTests { - - public static Stream params() { - return Stream.of(new GsonMapper(new Gson()), new JacksonMapper(new ObjectMapper())); - } - - @Test - public void objectNode_isJsonStringRepresentsCollection() { - ObjectNode node = JsonNodeFactory.instance.objectNode(); - node.put("id", "1234ab"); - node.put("foo", "bar"); - - /* - * Passing the ObjectNode directly results in a positive identification as - * a collection, as its distant parent JsonNode implements Iterable. - */ - assertThat(JsonMapper.isJsonStringRepresentsCollection(node)).isFalse(); - - String nodeAsString = node.toString(); - - /* - * Sending the node as a string returns false, however, as the line - * isJsonString(value) && str.startsWith("[") && str.endsWith("]") - * will not be true. - */ - assertThat(JsonMapper.isJsonStringRepresentsCollection(nodeAsString)).isFalse(); - } - - @ParameterizedTest - @MethodSource("params") - public void vanillaArray(JsonMapper mapper) { - String json = "[{\"value\":\"foo\"},{\"value\":\"foo\"}]"; - List list = mapper.fromJson(json, - ResolvableType.forClassWithGenerics(List.class, Foo.class).getType()); - assertThat(list).hasSize(2); - assertThat(list.get(0).getValue()).isEqualTo("foo"); - assertThat(mapper.toString(list)).isEqualTo(json); - } - - @ParameterizedTest - @MethodSource("params") - public void intArray(JsonMapper mapper) { - List list = mapper.fromJson("[123,456]", - ResolvableType.forClassWithGenerics(List.class, Integer.class).getType()); - assertThat(list).hasSize(2); - assertThat(list.get(0)).isEqualTo(123); - } - - @ParameterizedTest - @MethodSource("params") - public void emptyArray(JsonMapper mapper) { - List list = mapper.fromJson("[]", - ResolvableType.forClassWithGenerics(List.class, Foo.class).getType()); - assertThat(list).hasSize(0); - } - - @ParameterizedTest - @MethodSource("params") - public void vanillaObject(JsonMapper mapper) { - String json = "{\"value\":\"foo\"}"; - Foo foo = mapper.fromJson(json, Foo.class); - assertThat(foo.getValue()).isEqualTo("foo"); - assertThat(mapper.toString(foo)).isEqualTo(json); - } - - @ParameterizedTest - @MethodSource("params") - public void stringRepresentingJson(JsonMapper mapper) { - String json = "{\"value\":\"foo\"}"; - byte[] bytes = mapper.toJson(json); - assertThat(new String(bytes)).isEqualTo(json); - } - - @ParameterizedTest - @MethodSource("params") - public void intValue(JsonMapper mapper) { - int foo = mapper.fromJson("123", Integer.class); - assertThat(foo).isEqualTo(123); - } - - @ParameterizedTest - @MethodSource("params") - public void empty(JsonMapper mapper) { - Foo foo = mapper.fromJson("{}", Foo.class); - assertThat(foo.getValue()).isNull(); - } - - public static class Foo { - - private String value; - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-context/src/test/resources/avro/sensor.avsc b/spring-cloud-function-context/src/test/resources/avro/sensor.avsc deleted file mode 100644 index c0e060d3d..000000000 --- a/spring-cloud-function-context/src/test/resources/avro/sensor.avsc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "namespace" : "com.example", - "type" : "record", - "name" : "Sensor", - "fields" : [ - {"name":"id","type":"string"}, - {"name":"temperature", "type":"float", "default":0.0}, - {"name":"acceleration", "type":"float","default":0.0}, - {"name":"velocity","type":"float","default":0.0} - ] -} diff --git a/spring-cloud-function-context/src/test/resources/greeter.jar b/spring-cloud-function-context/src/test/resources/greeter.jar deleted file mode 100644 index 24671c2bacc48e6583eeb0bdc95abe63bf34674e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1015 zcmWIWW@Zs#;Nak3$mzS|#ef7j8CV#6T|*poJ^kGD|D9rBU}gyLX6FE@V1g7v*#$H@w>oU54?MO7XMY;6}=B4>WmEH>rZi8b0E*FO+i61J-9UH>YpzU@K6 z%0~`sUmtQU{*5>1bgsn}>HSN3)&+0Da549=(c<89N_E2*!z&%=3=dVoeCmV5+%NCz7*`9y8MQ3_vXT-(f@pB)V!H{ zYTrzQjUo$gg*xl{2yMPx7&pPNGcfVP`sWW0s9FC!RGBtCyW*}!=kHGrOVc0R?!3Pw zNZu}uqx;mJSEo_eg^YVeu@TSPpEQ1GkdJMg$o~Atgm6Y>!)dq77i9a%oGH@j zKgoK<;@3=u;uXe0RvYft9LZ|m_>uYCb7_%RM+LoR|LG0bH|tZC&9|y4FV}|8(lv13 z`u)wWjM)28*R!fWi{BB{x*Ya@d+63MK5>u7Leq}#_#_TWsnULr4dFZ z5eC$R4ok(LgpLZ}DHoLN(X}EcJy0@709zmvt`#ZKgG}IJz@0=9CL9JbkrOP!(V!%Y g>>*H+MS#~pCPE)d0uJzIWdkW>0m5HE`Z?I!09q1G@c;k- diff --git a/spring-cloud-function-core/.jdk8 b/spring-cloud-function-core/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-core/pom.xml b/spring-cloud-function-core/pom.xml deleted file mode 100644 index ef244ebc7..000000000 --- a/spring-cloud-function-core/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-core - jar - Spring Cloud Function Core - Spring Cloud Function Core - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - - io.projectreactor - reactor-core - - - org.springframework - spring-core - - - org.springframework.boot - spring-boot-starter-test - test - - - - diff --git a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionInvocationHelper.java b/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionInvocationHelper.java deleted file mode 100644 index ccd11c6e2..000000000 --- a/spring-cloud-function-core/src/main/java/org/springframework/cloud/function/core/FunctionInvocationHelper.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020-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.core; - - -/** - * - * @author Oleg Zhurakousky - * @since 3.1 - * - */ -public interface FunctionInvocationHelper { - - default boolean isRetainOuputAsMessage(I input) { - return true; - }; - - default I preProcessInput(I input, Object inputConverter) { - return input; - } - - default Object postProcessResult(Object result, I input) { - return result; - } -} diff --git a/spring-cloud-function-dependencies/pom.xml b/spring-cloud-function-dependencies/pom.xml deleted file mode 100644 index b10724181..000000000 --- a/spring-cloud-function-dependencies/pom.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - 4.0.0 - - spring-cloud-dependencies-parent - org.springframework.cloud - 4.1.0-SNAPSHOT - - - spring-cloud-function-dependencies - 4.1.0-SNAPSHOT - pom - Spring Cloud Function Dependencies - Spring Cloud Function Dependencies - - - - org.springframework.cloud - spring-cloud-function-context - ${project.version} - - - org.springframework.cloud - spring-cloud-function-core - ${project.version} - - - org.springframework.cloud - spring-cloud-function-web - ${project.version} - - - org.springframework.cloud - spring-cloud-starter-function-web - ${project.version} - - - org.springframework.cloud - spring-cloud-starter-function-webflux - ${project.version} - - - org.springframework.cloud - spring-cloud-function-deployer - ${project.version} - - - org.springframework.cloud - spring-cloud-function-adapter-aws - ${project.version} - - - org.springframework.cloud - spring-cloud-function-adapter-azure - ${project.version} - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - ${project.version} - - - org.springframework.cloud - spring-cloud-function-integration - ${project.version} - - - org.springframework.cloud - spring-cloud-function-kotlin - ${project.version} - - - org.springframework.cloud - spring-cloud-function-rsocket - ${project.version} - - - org.springframework.cloud - spring-cloud-function-grpc - ${project.version} - - - org.springframework.cloud - spring-cloud-function-grpc-cloudevent-ext - ${project.version} - - - org.springframework.cloud - spring-cloud-function-serverless-web - ${project.version} - - - - - - spring - - true - - - - - - 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-deployer/.gitignore b/spring-cloud-function-deployer/.gitignore deleted file mode 100644 index a2a3040aa..000000000 --- a/spring-cloud-function-deployer/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-deployer/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-deployer/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 72308aa47..000000000 --- a/spring-cloud-function-deployer/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you 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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-deployer/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-deployer/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997377a393fd672c7dcde9dccbedf0cb1e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48337 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 - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.0.RELEASE - - - - oz.demo - demo-stream - 0.0.1-SNAPSHOT - demo-stream - Demo project for Spring Boot - - - 1.8 - Hoxton.SR5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - - - - - - - - - - - diff --git a/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/maven-metadata-local.xml b/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/maven-metadata-local.xml deleted file mode 100644 index 98aed06e9..000000000 --- a/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/0.0.1-SNAPSHOT/maven-metadata-local.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - oz.demo - demo-stream - 0.0.1-SNAPSHOT - - - true - - 20200721131233 - - - jar - 0.0.1-SNAPSHOT - 20200721131233 - - - pom - 0.0.1-SNAPSHOT - 20200721131233 - - - - diff --git a/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/maven-metadata-local.xml b/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/maven-metadata-local.xml deleted file mode 100644 index bcc06a525..000000000 --- a/spring-cloud-function-deployer/mavenrepo/oz/demo/demo-stream/maven-metadata-local.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - oz.demo - demo-stream - - - 0.0.1-SNAPSHOT - - 20200721131233 - - diff --git a/spring-cloud-function-deployer/mvnw b/spring-cloud-function-deployer/mvnw deleted file mode 100755 index 8b9da3b8b..000000000 --- a/spring-cloud-function-deployer/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-deployer/mvnw.cmd b/spring-cloud-function-deployer/mvnw.cmd deleted file mode 100644 index fef5a8f7f..000000000 --- a/spring-cloud-function-deployer/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-deployer/pom.xml b/spring-cloud-function-deployer/pom.xml deleted file mode 100644 index b61c18fde..000000000 --- a/spring-cloud-function-deployer/pom.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - 4.0.0 - spring-cloud-function-deployer - jar - spring-cloud-function-deployer - Spring Cloud Function Deployer - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - 17 - - - - - org.springframework.boot - spring-boot-loader - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.cloud - spring-cloud-deployer-resource-maven - 2.5.1 - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - io.cloudevents - cloudevents-spring - 2.2.0 - test - - - - - - - org.apache.maven.plugins - maven-invoker-plugin - 3.0.1 - - ${project.build.directory}/local-repo - - - - - prepare-test - test-compile - - run - - - ${project.build.directory}/it - - src/it/settings.xml - true - true - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.apache.maven.plugins - - - maven-invoker-plugin - - - [3.0.1,) - - - run - - - - - - - - - - - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - - diff --git a/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml b/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml deleted file mode 100644 index 5e3f1e2ba..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-multi/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - 4.0.0 - - function.example - bootapp-multi - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - io.projectreactor - reactor-core - 3.1.2.RELEASE - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootapp-multi/src/main/java/function/example/MyFn.java b/spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/MyFn.java deleted file mode 100644 index dd07b1d6d..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/MyFn.java +++ /dev/null @@ -1,29 +0,0 @@ -package function.example; - -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import java.util.Collections; -import java.util.function.Function; - -public class MyFn implements Function, Flux>, Tuple2, Flux>> { - - - @Override - public Tuple2, Flux> apply(Tuple2, Flux> inputs) { - Flux words = inputs.getT1(); - Flux numbers = inputs.getT2().publish().autoConnect(2); - - - Flux avg = numbers.buffer(2, 1) - .map(l -> l.stream().mapToInt(Integer::intValue).average().getAsDouble()) - .take(3); - - Flux repeated = words.zipWith(numbers) - .flatMap(t -> Flux.fromIterable(Collections.nCopies(t.getT2(), t.getT1()))); - - return Tuples.of(avg, repeated); - - } -} diff --git a/spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/RepeaterApplication.java b/spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/RepeaterApplication.java deleted file mode 100644 index 73f4d9c94..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-multi/src/main/java/function/example/RepeaterApplication.java +++ /dev/null @@ -1,80 +0,0 @@ -package function.example; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; - -import java.util.function.Function; - -@SpringBootApplication -public class RepeaterApplication { - - @Bean - public Function, Flux>, Flux> fn() { - return tuple -> { - Flux cartEventStream = tuple.getT1(); - Flux checkoutEventStream = tuple.getT2(); - - return Flux.zip(cartEventStream, checkoutEventStream, (cartEvent, checkoutEvent) -> { - OrderEvent oe = new OrderEvent(); - oe.setOrderEvent(cartEvent.toString() + "- " + checkoutEvent.toString()); - return oe; - }); - }; - } - - public static void main(String[] args) { - SpringApplication.run(RepeaterApplication.class, args); - } - - public static class CartEvent { - private String carEvent; - - public String getCarEvent() { - return carEvent; - } - - public void setCarEvent(String carEvent) { - this.carEvent = carEvent; - } - - public String toString() { - return "CartEvent: " + carEvent; - } - } - - public static class CheckoutEvent { - private String checkoutEvent; - - public String getCheckoutEvent() { - return checkoutEvent; - } - - public void setCheckoutEvent(String checkoutEvent) { - this.checkoutEvent = checkoutEvent; - } - - public String toString() { - return "CheckoutEvent: " + checkoutEvent; - } - } - - public static class OrderEvent { - private String orderEvent; - - public String getOrderEvent() { - return orderEvent; - } - - public void setOrderEvent(String orderEvent) { - this.orderEvent = orderEvent; - } - - public String toString() { - return "OrderEvent: " + orderEvent; - } - } - -} 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 deleted file mode 100644 index 98ff289a4..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-javax/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - 4.0.0 - - function.example - bootapp-with-javax - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - com.sun.mail - javax.mail - 1.6.2 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootapp-with-javax/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/SimpleFunctionAppApplication.java deleted file mode 100644 index ed8f694ef..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/SimpleFunctionAppApplication.java +++ /dev/null @@ -1,57 +0,0 @@ -package function.example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } - - @Bean - public Function uppercase() { - System.out.println("==> CREATING 'uppercase' FUNCTION bean"); - return new UpperCaseFunction(); - } - - @Bean - public Function uppercasePerson() { - System.out.println("==> CREATING 'uppercasePerson' FUNCTION bean"); - return person -> { - Person p = new Person(); - p.setId(person.getId()); - p.setName(person.getName().toUpperCase()); - return p; - }; - } - - - - public static class Person { - private String name; - - private int id; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - } -} diff --git a/spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/UpperCaseFunction.java deleted file mode 100644 index 735ad65fb..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-javax/src/main/java/function/example/UpperCaseFunction.java +++ /dev/null @@ -1,23 +0,0 @@ -package function.example; - -import java.util.function.Function; - -import javax.mail.Address; -import javax.mail.internet.AddressException; -import javax.mail.internet.InternetAddress; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - try { - Address address = new InternetAddress(value); - } - catch (AddressException e) { - throw new IllegalStateException("Failed to create and address: ", e); - } - return value.toUpperCase(); - } - -} 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 deleted file mode 100644 index f82f988c3..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-scf/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - 4.0.0 - - function.example - bootapp-with-scf - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-function-context - ${spring-cloud-function.version} - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootapp-with-scf/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/SimpleFunctionAppApplication.java deleted file mode 100644 index 63e0719c3..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/SimpleFunctionAppApplication.java +++ /dev/null @@ -1,63 +0,0 @@ -package function.example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -@SpringBootApplication -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } - - @Bean - public Function, Message> uppercase() { - System.out.println("==> CREATING 'uppercase' FUNCTION bean"); - return message -> { - UpperCaseFunction func = new UpperCaseFunction(); - String result = func.apply(message.getPayload()); - return MessageBuilder.withPayload(result).build(); - }; - } - - @Bean - public Function uppercasePerson() { - System.out.println("==> CREATING 'uppercasePerson' FUNCTION bean"); - return person -> { - Person p = new Person(); - p.setId(person.getId()); - p.setName(person.getName().toUpperCase()); - return p; - }; - } - - - - public static class Person { - private String name; - - private int id; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - } -} diff --git a/spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/UpperCaseFunction.java deleted file mode 100644 index 859a54a58..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp-with-scf/src/main/java/function/example/UpperCaseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package function.example; - -import java.util.function.Function; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - return value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-deployer/src/it/bootapp/pom.xml b/spring-cloud-function-deployer/src/it/bootapp/pom.xml deleted file mode 100644 index 64a0da2fe..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - 4.0.0 - - function.example - bootapp - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java deleted file mode 100644 index ed8f694ef..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/SimpleFunctionAppApplication.java +++ /dev/null @@ -1,57 +0,0 @@ -package function.example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } - - @Bean - public Function uppercase() { - System.out.println("==> CREATING 'uppercase' FUNCTION bean"); - return new UpperCaseFunction(); - } - - @Bean - public Function uppercasePerson() { - System.out.println("==> CREATING 'uppercasePerson' FUNCTION bean"); - return person -> { - Person p = new Person(); - p.setId(person.getId()); - p.setName(person.getName().toUpperCase()); - return p; - }; - } - - - - public static class Person { - private String name; - - private int id; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - } -} diff --git a/spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java deleted file mode 100644 index 859a54a58..000000000 --- a/spring-cloud-function-deployer/src/it/bootapp/src/main/java/function/example/UpperCaseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package function.example; - -import java.util.function.Function; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - return value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml b/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml deleted file mode 100644 index 227adef52..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar-multi/pom.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - 4.0.0 - - function.example - bootjar-multi - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - io.projectreactor - reactor-core - 3.1.2.RELEASE - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - NONE - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootjar-multi/src/main/java/function/example/Repeater.java b/spring-cloud-function-deployer/src/it/bootjar-multi/src/main/java/function/example/Repeater.java deleted file mode 100644 index 643b9475d..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar-multi/src/main/java/function/example/Repeater.java +++ /dev/null @@ -1,27 +0,0 @@ -package function.example; - -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import java.util.Collections; -import java.util.function.Function; - -public class Repeater implements Function, Flux>, Tuple2, Flux>> { - - @Override - public Tuple2, Flux> apply(Tuple2, Flux> inputs) { - Flux stringFlux = inputs.getT1(); - Flux integerFlux = inputs.getT2(); - Flux sharedIntFlux = integerFlux.publish().autoConnect(2); - - Flux repeated = stringFlux.zipWith(sharedIntFlux) - .flatMap(t -> Flux.fromIterable(Collections.nCopies(t.getT2(), t.getT1()))); - - Flux sum = sharedIntFlux.buffer(2, 1) - .map(l -> l.stream().mapToInt(Integer::intValue).sum()) - ; - - return Tuples.of(repeated, sum); - } -} diff --git a/spring-cloud-function-deployer/src/it/bootjar/pom.xml b/spring-cloud-function-deployer/src/it/bootjar/pom.xml deleted file mode 100644 index 6231f61a4..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - 4.0.0 - - function.example - bootjar - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootjar/src/main/java/function/example/ReverseFunction.java b/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/ReverseFunction.java deleted file mode 100644 index 090a28e2e..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/ReverseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package function.example; - -import java.util.function.Function; - -public class ReverseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Reversing " + value); - return new StringBuilder(value).reverse().toString(); - } - -} diff --git a/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java b/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java deleted file mode 100644 index 5d5eaf3ea..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/SimpleFunctionAppApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package function.example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -public class SimpleFunctionAppApplication { - - public static void main(String[] args) { - SpringApplication.run(SimpleFunctionAppApplication.class, args); - } -} diff --git a/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java deleted file mode 100644 index 859a54a58..000000000 --- a/spring-cloud-function-deployer/src/it/bootjar/src/main/java/function/example/UpperCaseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package function.example; - -import java.util.function.Function; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - return value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml b/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml deleted file mode 100644 index 42cb49ef7..000000000 --- a/spring-cloud-function-deployer/src/it/bootjarnostart/pom.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - 4.0.0 - - function.example - bootjarnostart - 1.0.0.RELEASE - jar - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 17 - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - NONE - exec - - - - org.apache.maven.plugins - maven-jar-plugin - - - - function.example.UpperCaseFunction - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack - package - - unpack - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - exec - - - - - - - - - - - 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-deployer/src/it/bootjarnostart/src/main/java/function/example/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/bootjarnostart/src/main/java/function/example/UpperCaseFunction.java deleted file mode 100644 index 859a54a58..000000000 --- a/spring-cloud-function-deployer/src/it/bootjarnostart/src/main/java/function/example/UpperCaseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package function.example; - -import java.util.function.Function; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - return value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-deployer/src/it/settings.xml b/spring-cloud-function-deployer/src/it/settings.xml deleted file mode 100644 index e1e0ace34..000000000 --- a/spring-cloud-function-deployer/src/it/settings.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - it-repo - - true - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - diff --git a/spring-cloud-function-deployer/src/it/simplestjar/pom.xml b/spring-cloud-function-deployer/src/it/simplestjar/pom.xml deleted file mode 100644 index 8eaa026d9..000000000 --- a/spring-cloud-function-deployer/src/it/simplestjar/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - - function.example - simplestjar - 1.0.0.RELEASE - jar - - simplestjar - - - UTF-8 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - - package - - shade - - - - - - - - - - io.cloudevents - cloudevents-api - 2.2.0 - true - - - - - diff --git a/spring-cloud-function-deployer/src/it/simplestjar/src/main/java/function/example/EchoCloudEventFunction.java b/spring-cloud-function-deployer/src/it/simplestjar/src/main/java/function/example/EchoCloudEventFunction.java deleted file mode 100644 index 0dc913143..000000000 --- a/spring-cloud-function-deployer/src/it/simplestjar/src/main/java/function/example/EchoCloudEventFunction.java +++ /dev/null @@ -1,16 +0,0 @@ -package function.example; - -import java.util.Map; -import java.util.function.Function; - -import io.cloudevents.CloudEvent; - -public class EchoCloudEventFunction implements Function { - - @Override - public CloudEvent apply(CloudEvent value) { - System.out.println("Received " + value); - return value; - } - -} diff --git a/spring-cloud-function-deployer/src/it/simplestjarcs/pom.xml b/spring-cloud-function-deployer/src/it/simplestjarcs/pom.xml deleted file mode 100644 index 503556277..000000000 --- a/spring-cloud-function-deployer/src/it/simplestjarcs/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - 4.0.0 - - function.example - simplestjarcs - 1.0.0.RELEASE - Showcases compoinent scanning capabilities - jar - - simplestjarcs - - - UTF-8 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - - - - diff --git a/spring-cloud-function-deployer/src/it/simplestjarcs/src/main/java/functions/UpperCaseFunction.java b/spring-cloud-function-deployer/src/it/simplestjarcs/src/main/java/functions/UpperCaseFunction.java deleted file mode 100644 index 07f535dc1..000000000 --- a/spring-cloud-function-deployer/src/it/simplestjarcs/src/main/java/functions/UpperCaseFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package functions; - -import java.util.function.Function; - -public class UpperCaseFunction implements Function { - - @Override - public String apply(String value) { - System.out.println("Uppercasing " + value); - return value.toUpperCase(); - } - -} diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployerContextUtils.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployerContextUtils.java deleted file mode 100644 index 070328b0d..000000000 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/DeployerContextUtils.java +++ /dev/null @@ -1,121 +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.deployer; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.ConstructorArgumentValues; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.core.ResolvableType; -import org.springframework.core.io.Resource; -import org.springframework.core.type.MethodMetadata; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -/** - * @author Oleg Zhurakousky - * @since 3.0 - */ -abstract class DeployerContextUtils { - - public static Type findType(BeanFactory beanFactory, String name) { - ConfigurableListableBeanFactory registry = (ConfigurableListableBeanFactory) beanFactory; - AbstractBeanDefinition definition = (AbstractBeanDefinition) registry.getBeanDefinition(name); - - Object source = definition.getSource(); - - Type param = null; - if (source instanceof MethodMetadata) { - param = findBeanType(definition, ((MethodMetadata) source).getDeclaringClassName(), ((MethodMetadata) source).getMethodName()); - } - else if (source instanceof Resource) { - param = registry.getType(name); - } - else { - ResolvableType type = (ResolvableType) getField(definition, "targetType"); - if (type != null) { - param = type.getType(); - } - } - return param; - } - - private static Type findBeanType(AbstractBeanDefinition definition, String declaringClassName, String methodName) { - Class factory = ClassUtils.resolveClassName(declaringClassName, null); - Class[] params = getParamTypes(factory, definition); - Method method = ReflectionUtils.findMethod(factory, methodName, - params); - Type type = method.getGenericReturnType(); - return type; - } - - private static Class[] getParamTypes(Class factory, - AbstractBeanDefinition definition) { - if (definition instanceof RootBeanDefinition) { - RootBeanDefinition root = (RootBeanDefinition) definition; - for (Method method : getCandidateMethods(factory, root)) { - if (root.isFactoryMethod(method)) { - return method.getParameterTypes(); - } - } - } - List> params = new ArrayList<>(); - for (ConstructorArgumentValues.ValueHolder holder : definition - .getConstructorArgumentValues().getIndexedArgumentValues().values()) { - params.add(ClassUtils.resolveClassName(holder.getType(), null)); - } - return params.toArray(new Class[0]); - } - - private static Method[] getCandidateMethods(final Class factoryClass, - final RootBeanDefinition mbd) { - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Method[] run() { - return (mbd.isNonPublicAccessAllowed() - ? ReflectionUtils.getAllDeclaredMethods(factoryClass) - : factoryClass.getMethods()); - } - }); - } - else { - return (mbd.isNonPublicAccessAllowed() - ? ReflectionUtils.getAllDeclaredMethods(factoryClass) - : factoryClass.getMethods()); - } - } - - private static Object getField(Object target, String name) { - Field field = ReflectionUtils.findField(target.getClass(), name); - if (field == null) { - return null; - } - ReflectionUtils.makeAccessible(field); - return ReflectionUtils.getField(field, target); - } - -} diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionArchiveDeployer.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionArchiveDeployer.java deleted file mode 100644 index 2c96fdd64..000000000 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionArchiveDeployer.java +++ /dev/null @@ -1,337 +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.deployer; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.regex.Pattern; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.loader.JarLauncher; -import org.springframework.boot.loader.LaunchedURLClassLoader; -import org.springframework.boot.loader.archive.Archive; -import org.springframework.boot.loader.jar.JarFile; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; -import org.springframework.core.type.filter.RegexPatternTypeFilter; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.expression.spel.support.StandardTypeLocator; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.ReflectionUtils.MethodCallback; -import org.springframework.util.ReflectionUtils.MethodFilter; -import org.springframework.util.StreamUtils; -import org.springframework.util.StringUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.0 - * - */ -class FunctionArchiveDeployer extends JarLauncher { - - private static Log logger = LogFactory.getLog(FunctionArchiveDeployer.class); - - private final StandardEvaluationContext evalContext = new StandardEvaluationContext(); - - private LaunchedURLClassLoader archiveLoader; - - FunctionArchiveDeployer(Archive archive) { - super(archive); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - void deploy(FunctionRegistry functionRegistry, FunctionDeployerProperties functionProperties, String[] args, ApplicationContext applicationContext) { - ClassLoader currentLoader = Thread.currentThread().getContextClassLoader(); - - try { - ClassLoader cl = createClassLoader(discoverClassPathAcrhives().iterator()); - - Thread.currentThread().setContextClassLoader(cl); - - - evalContext.setTypeLocator(new StandardTypeLocator(Thread.currentThread().getContextClassLoader())); - - if (this.isBootApplicationWithMain()) { - this.launchFunctionArchive(args); - - Map functions = this.discoverBeanFunctions(); - if (logger.isInfoEnabled() && !CollectionUtils.isEmpty(functions)) { - logger.info("Discovered functions in deployed application context: " + functions); - } - for (Entry entry : functions.entrySet()) { - FunctionRegistration registration = new FunctionRegistration(entry.getValue(), entry.getKey()); - Type type = this.discoverFunctionType(entry.getKey()); - if (logger.isInfoEnabled()) { - logger.info("Registering function '" + entry.getKey() + "' of type '" + type - + "' in FunctionRegistry."); - } - registration.type(type); - functionRegistry.register(registration); - } - } - - String[] functionClassNames = discoverFunctionClassName(functionProperties); - - if (functionClassNames == null) { - ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner((BeanDefinitionRegistry) applicationContext, false); - scanner.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*"))); - Set findCandidateComponents = scanner.findCandidateComponents("functions"); - - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - for (BeanDefinition beanDefinition : findCandidateComponents) { - String className = beanDefinition.getBeanClassName(); - Class functionClass = currentClassLoader.loadClass(className); - if (Function.class.isAssignableFrom(functionClass) || Supplier.class.isAssignableFrom(functionClass) || Consumer.class.isAssignableFrom(functionClass)) { - FunctionRegistration registration = this.discovereAndLoadFunctionFromClassName(className); - if (registration != null) { - functionRegistry.register(registration); - } - } - } - } - else { - for (String functionClassName : functionClassNames) { - if (StringUtils.hasText(functionClassName)) { - FunctionRegistration registration = this.discovereAndLoadFunctionFromClassName(functionClassName); - if (registration != null) { - functionRegistry.register(registration); - } - } - } - } - } - catch (Exception e) { - throw new IllegalStateException("Failed to deploy archive " + this.getArchive(), e); - } - finally { - Thread.currentThread().setContextClassLoader(currentLoader); - } - } - - void undeploy() { - this.stopDeployedApplicationContext(); - try { - this.archiveLoader.close(); - logger.info("Closed archive class loader"); - } - catch (IOException e) { - logger.error("Failed to closed archive class loader", e); - } - } - - @Override - protected ClassLoader createClassLoader(URL[] urls) throws Exception { - String classAsPath = DeployerContextUtils.class.getName().replace('.', '/') + ".class"; - byte[] deployerContextUtilsBytes = StreamUtils - .copyToByteArray(DeployerContextUtils.class.getClassLoader().getResourceAsStream(classAsPath)); - /* - * While LaunchedURLClassLoader is completely disconnected with the current - * class loader, this will ensure that certain classes (e.g., org.reactivestreams.* see #shouldLoadViaDeployerLoader() ) - * are shared across two class loaders. - */ - final ClassLoader deployerClassLoader = getClass().getClassLoader(); - this.archiveLoader = new LaunchedURLClassLoader(urls, deployerClassLoader.getParent()) { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - Class clazz = null; - if (shouldLoadViaDeployerLoader(name)) { - clazz = deployerClassLoader.loadClass(name); - } - else if (name.equals(DeployerContextUtils.class.getName())) { - /* - * This will ensure that `DeployerContextUtils` is available to - * foreign class loader for cases where foreign JAR does not - * have SCF dependencies. - */ - try { - clazz = super.loadClass(name, false); - } - catch (Exception e) { - clazz = defineClass(name, deployerContextUtilsBytes, 0, deployerContextUtilsBytes.length); - } - } - else { - clazz = super.loadClass(name, false); - } - return clazz; - } - }; - return this.archiveLoader; - } - - private boolean shouldLoadViaDeployerLoader(String name) { - return name.startsWith("org.reactivestreams") - || name.startsWith("reactor.") - || name.startsWith("io.cloudevents") - || name.startsWith("org.springframework.messaging.Message") - || name.startsWith("org.springframework.messaging.converter.MessageConverter"); - } - - - - private String[] discoverFunctionClassName(FunctionDeployerProperties functionProperties) { - try { - if (StringUtils.hasText(functionProperties.getFunctionClass())) { - return functionProperties.getFunctionClass().split(";"); - } - else if (StringUtils.hasText(this.getArchive().getManifest().getMainAttributes().getValue("Function-Class"))) { - return new String[] {this.getArchive().getManifest().getMainAttributes().getValue("Function-Class")}; - } - else { - return null; - } - } - catch (Exception e) { - throw new IllegalStateException("Failed to discover function class name", e); - } - } - - private boolean isBootApplicationWithMain() { - try { - if (this.getArchive().getManifest() == null) { - return false; - } - return StringUtils.hasText(this.getArchive().getManifest().getMainAttributes().getValue("Start-Class")); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - - private List discoverClassPathAcrhives() throws Exception { - Iterator iter = this.getClassPathArchivesIterator(); - List classPathArchives = new ArrayList<>(); - while (iter.hasNext()) { - classPathArchives.add(iter.next()); - } - - if (CollectionUtils.isEmpty(classPathArchives)) { - classPathArchives.add(this.getArchive()); - } - return classPathArchives; - } - - private FunctionRegistration discovereAndLoadFunctionFromClassName(String functionClassName) throws Exception { - FunctionRegistration functionRegistration = null; - AtomicReference typeRef = new AtomicReference<>(); - Class functionClass = Thread.currentThread().getContextClassLoader().loadClass(functionClassName); - - ReflectionUtils.doWithMethods(functionClass, new MethodCallback() { - @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - typeRef.set(FunctionTypeUtils.discoverFunctionTypeFromFunctionMethod(method)); - } - }, new MethodFilter() { - @Override - public boolean matches(Method method) { - String name = method.getName(); - return typeRef.get() == null && !method.isBridge() - && ("apply".equals(name) || "accept".equals(name) || "get".equals(name)); - } - }); - - if (typeRef.get() != null) { - Object functionInstance = functionClass.newInstance(); - String functionName = StringUtils.uncapitalize(functionClass.getSimpleName()); - if (logger.isInfoEnabled()) { - logger.info("Registering function class '" + functionClass + "' of type '" + typeRef.get() - + "' under name '" + functionName + "'."); - } - functionRegistration = new FunctionRegistration<>(functionInstance, functionName); - functionRegistration.type(typeRef.get()); - } - return functionRegistration; - } - - private void launchFunctionArchive(String[] args) throws Exception { - JarFile.registerUrlProtocolHandler(); - - String mainClassName = getMainClass(); - Class mainClass = Thread.currentThread().getContextClassLoader().loadClass(mainClassName); - - Class bootAppClass = Thread.currentThread().getContextClassLoader() - .loadClass(SpringApplication.class.getName()); - Method runMethod = bootAppClass.getDeclaredMethod("run", Class.class, String[].class); - Object applicationContext = runMethod.invoke(null, mainClass, args); - if (logger.isInfoEnabled()) { - logger.info("Application context for archive '" + this.getArchive().getUrl() + "' is created."); - } - evalContext.setVariable("context", applicationContext); - setBeanFactory(applicationContext); - } - - private void setBeanFactory(Object applicationContext) { - Expression parsed = new SpelExpressionParser().parseExpression("#context.getBeanFactory()"); - Object beanFactory = parsed.getValue(this.evalContext); - evalContext.setVariable("bf", beanFactory); - } - - private Type discoverFunctionType(String name) { - evalContext.setVariable("functionName", name); - String expr = "T(" + DeployerContextUtils.class.getName() + ").findType(#bf, #functionName)"; - Expression parsed = new SpelExpressionParser().parseExpression(expr); - Object type = parsed.getValue(this.evalContext); - return (Type) type; - } - - private void stopDeployedApplicationContext() { - if (evalContext.lookupVariable("context") != null) { // no start-class uber jars - Expression parsed = new SpelExpressionParser().parseExpression("#context.stop()"); - parsed.getValue(this.evalContext); - } - } - - @SuppressWarnings("unchecked") - private Map discoverBeanFunctions() { - Map allFunctions = new HashMap(); - if (evalContext.lookupVariable("context") != null) { // no start-class uber jars - Expression parsed = new SpelExpressionParser() - .parseExpression("#context.getBeansOfType(T(java.util.function.Function))"); - allFunctions.putAll((Map) parsed.getValue(this.evalContext)); - parsed = new SpelExpressionParser().parseExpression("#context.getBeansOfType(T(java.util.function.Supplier))"); - allFunctions.putAll((Map) parsed.getValue(this.evalContext)); - parsed = new SpelExpressionParser().parseExpression("#context.getBeansOfType(T(java.util.function.Consumer))"); - allFunctions.putAll((Map) parsed.getValue(this.evalContext)); - } - return allFunctions; - } -} diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerConfiguration.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerConfiguration.java deleted file mode 100644 index 2105c5b0d..000000000 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerConfiguration.java +++ /dev/null @@ -1,187 +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.deployer; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.DefaultApplicationArguments; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.boot.loader.archive.Archive; -import org.springframework.boot.loader.archive.ExplodedArchive; -import org.springframework.boot.loader.archive.JarFileArchive; -import org.springframework.cloud.deployer.resource.maven.MavenProperties; -import org.springframework.cloud.deployer.resource.maven.MavenResourceLoader; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.context.ApplicationContext; -import org.springframework.context.SmartLifecycle; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertiesPropertySource; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * - * Configuration class which creates an instance of {@link SmartLifecycle} - * which deploys and un-deploys packages archives via it's {@link SmartLifecycle#start()} - * and {@link SmartLifecycle#stop()} operations. - *
- * @author Oleg Zhurakousky - * @author Eric Bottard - * - * @since 3.0 - * - */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(FunctionDeployerProperties.class) -@ConditionalOnProperty(name = FunctionProperties.PREFIX + ".location") -public class FunctionDeployerConfiguration { - - private static Log logger = LogFactory.getLog(FunctionDeployerConfiguration.class); - - @Bean - SmartLifecycle functionArchiveUnDeployer(FunctionDeployerProperties functionProperties, - FunctionRegistry functionRegistry, ApplicationArguments arguments, @Nullable MavenProperties mavenProperties, ApplicationContext applicationContext) { - - ApplicationArguments updatedArguments = this.updateArguments(arguments); - - Archive archive = null; - try { - File file; - String location = functionProperties.getLocation(); - Assert.hasText(location, "`spring.cloud.function.location` property must be defined."); - if (location.startsWith("maven://")) { - MavenResourceLoader resourceLoader = new MavenResourceLoader(mavenProperties); - file = resourceLoader.getResource(location).getFile(); - } - else { - file = new File(location); - } - - if (!file.exists()) { - throw new IllegalStateException("Failed to create archive: " + functionProperties.getLocation() + " does not exist"); - } - else if (file.isDirectory()) { - archive = new ExplodedArchive(file); - } - else { - archive = new JarFileArchive(file); - } - } - catch (IOException e) { - throw new IllegalStateException("Failed to create archive: " + functionProperties.getLocation(), e); - } - FunctionArchiveDeployer deployer = new FunctionArchiveDeployer(archive); - - if (logger.isInfoEnabled()) { - logger.info("Deploying archive: " + functionProperties.getLocation()); - } - deployer.deploy(functionRegistry, functionProperties, updatedArguments.getSourceArgs(), applicationContext); - if (logger.isInfoEnabled()) { - logger.info("Successfully deployed archive: " + functionProperties.getLocation()); - } - - return new SmartLifecycle() { - - private boolean running = true; - - @Override - public void stop() { - if (logger.isInfoEnabled()) { - logger.info("Undeploying archive: " + functionProperties.getLocation()); - } - deployer.undeploy(); - if (logger.isInfoEnabled()) { - logger.info("Successfully undeployed archive: " + functionProperties.getLocation()); - } - this.running = false; - } - - @Override - public void start() { - // no op - } - - @Override - public boolean isRunning() { - return this.running; - } - - @Override - public int getPhase() { - return Integer.MAX_VALUE - 1000; - } - }; - - } - - /* - * We need to update the actual arguments with non-legacy properties before passing these arguments to the deployable archive. - * For the current application FunctionProperties already updated and set as a result of EnvironmentPostProcessor - */ - private ApplicationArguments updateArguments(ApplicationArguments arguments) { - List originalArguments = new ArrayList(Arrays.asList(arguments.getSourceArgs())); - - if (arguments.containsOption("function.name")) { - originalArguments.add(FunctionProperties.PREFIX + ".definition=" + arguments.getOptionValues("function.name").get(0)); - } - if (arguments.containsOption("function.location")) { - originalArguments.add(FunctionProperties.PREFIX + ".location=" + arguments.getOptionValues("function.location").get(0)); - } - ApplicationArguments updatedArguments = new DefaultApplicationArguments(originalArguments.toArray(new String[] {})); - return updatedArguments; - } - - - /** - * Instance of {@link EnvironmentPostProcessor} which ensures that legacy - * Function property names are still honored. - */ - static class LegacyPropertyEnvironmentPostProcessor implements EnvironmentPostProcessor { - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - String functionName = environment.containsProperty("function.name") ? environment.getProperty("function.name") : null; - String functionLocation = environment.containsProperty("function.location") ? environment.getProperty("function.location") : null; - if (StringUtils.hasText(functionName) || StringUtils.hasText(functionLocation)) { - MutablePropertySources propertySources = environment.getPropertySources(); - propertySources.forEach(ps -> { - if (ps instanceof PropertiesPropertySource) { - ((MapPropertySource) ps).getSource().put(FunctionProperties.PREFIX + ".definition", functionName); - ((MapPropertySource) ps).getSource().put(FunctionProperties.PREFIX + ".location", functionLocation); - } - }); - } - } - } - -} diff --git a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerProperties.java b/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerProperties.java deleted file mode 100644 index e5e61c779..000000000 --- a/spring-cloud-function-deployer/src/main/java/org/springframework/cloud/function/deployer/FunctionDeployerProperties.java +++ /dev/null @@ -1,69 +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.deployer; - -import jakarta.annotation.PostConstruct; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.util.Assert; - - -/** - * Configuration properties for deciding how to locate the functional class to execute. - * - * @author Eric Bottard - * @author Oleg Zhurakousky - * - * @see FunctionProperties - */ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX) -public class FunctionDeployerProperties { - - /** - * Location of jar archive containing the supplier/function/consumer class or bean to run. - */ - private String location; - - /** - * The name of the function class to be instantiated and loaded into FunctionCatalog. The name of the - * function will be decapitalized simple name of this class. - */ - private String functionClass; - - public void setFunctionClass(String functionClass) { - this.functionClass = functionClass; - } - - public String getFunctionClass() { - return this.functionClass; - } - - public String getLocation() { - return this.location; - } - - public void setLocation(String location) { - this.location = location; - } - - @PostConstruct - public void init() { - Assert.notNull(this.location, "No archive location provided, please configure spring.cloud.function.location as a jar or directory."); - } - -} diff --git a/spring-cloud-function-deployer/src/main/resources/META-INF/spring.factories b/spring-cloud-function-deployer/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 55304d26b..000000000 --- a/spring-cloud-function-deployer/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.cloud.function.deployer.FunctionDeployerConfiguration$LegacyPropertyEnvironmentPostProcessor diff --git a/spring-cloud-function-deployer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-deployer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index c792ab9e6..000000000 --- a/spring-cloud-function-deployer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.deployer.FunctionDeployerConfiguration diff --git a/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java b/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java deleted file mode 100644 index c9ae26965..000000000 --- a/spring-cloud-function-deployer/src/test/java/org/springframework/cloud/function/deployer/FunctionDeployerTests.java +++ /dev/null @@ -1,439 +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.deployer; - - - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.deployer.resource.maven.MavenProperties; -import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.MessageBuilder; - - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @since 3.0 - */ -public class FunctionDeployerTests { - - @BeforeEach - public void before() { - System.clearProperty("spring.cloud.function.definition"); - } - - @Test - public void testWithMavenConfiguration() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=maven://oz.demo:demo-stream:0.0.1-SNAPSHOT", - "--spring.cloud.function.function-class=oz.demo.demostream.MyFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("myFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - } - - /* - * Target function `class UpperCaseFunction implements Function` - * Main/Start class present, no Spring configuration - */ - @Test - public void testWithMainAndStartClassNoSpringConfiguration() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootjar/target/bootjar-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-class=function.example.UpperCaseFunction;function.example.ReverseFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("upperCaseFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - assertThat(function.apply("stacy")).isEqualTo("STACY"); - - function = catalog.lookup("reverseFunction"); - - assertThat(function.apply("bob")).isEqualTo("bob"); - assertThat(function.apply("stacy")).isEqualTo("ycats"); - - Function, Flux> functionAsFlux = catalog.lookup("upperCaseFunction"); - - List results = functionAsFlux.apply(Flux.just("bob", "stacy")).collectList().block(); - assertThat(results.get(0)).isEqualTo("BOB"); - assertThat(results.get(1)).isEqualTo("STACY"); - - functionAsFlux = catalog.lookup("reverseFunction"); - - results = functionAsFlux.apply(Flux.just("bob", "stacy")).collectList().block(); - - assertThat(results.get(0)).isEqualTo("bob"); - assertThat(results.get(1)).isEqualTo("ycats"); - } - - @Test - public void testWithSimplestJar() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/simplestjar/target/simplestjar-1.0.0.RELEASE.jar", - "--spring.cloud.function.function-class=function.example.EchoCloudEventFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("echoCloudEventFunction"); - - String data = "{\"name\":\"Ricky\"}"; - Message inputMessage = CloudEventMessageBuilder - .withData(data) - .setId("123") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setSource("https://spring.io/") - .setType("org.springframework") - .build(); - - assertThat(new String(function.apply(inputMessage).getPayload())).isEqualTo(data); - } - - @Test - public void testWithSimplestJarComponentScanning() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/simplestjarcs/target/simplestjarcs-1.0.0.RELEASE.jar"}; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("upperCaseFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - assertThat(function.apply("stacy")).isEqualTo("STACY"); - - Function, Flux> functionAsFlux = catalog.lookup("upperCaseFunction"); - - List results = functionAsFlux.apply(Flux.just("bob", "stacy")).collectList().block(); - assertThat(results.get(0)).isEqualTo("BOB"); - assertThat(results.get(1)).isEqualTo("STACY"); - } - - @Test - public void testWithSimplestJarExploaded() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/simplestjar/target/classes", - "--spring.cloud.function.function-class=function.example.EchoCloudEventFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("echoCloudEventFunction"); - - String data = "{\"name\":\"Ricky\"}"; - Message inputMessage = CloudEventMessageBuilder - .withData(data) - .setId("123") - .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") - .setSource("https://spring.io/") - .setType("org.springframework") - .build(); - - assertThat(new String(function.apply(inputMessage).getPayload())).isEqualTo(data); - - Function>, Flux>> functionAsFlux = catalog.lookup("echoCloudEventFunction"); - - List> results = functionAsFlux.apply(Flux.just(inputMessage)).collectList().block(); - assertThat(results.get(0).getPayload()).isEqualTo(data.getBytes()); - //assertThat(results.get(1)).isEqualTo("STACY"); - } - - /* - * Target function `class UpperCaseFunction implements Function` - * No Main/Start class present, no Spring configuration - */ - @Test - public void testNoMainAndNoStartClassAndNoSpringConfiguration() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootjarnostart/target/bootjarnostart-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-class=function.example.UpperCaseFunction" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("upperCaseFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - assertThat(function.apply("stacy")).isEqualTo("STACY"); - - Function, Flux> functionAsFlux = catalog.lookup("upperCaseFunction"); - - List results = functionAsFlux.apply(Flux.just("bob", "stacy")).collectList().block(); - assertThat(results.get(0)).isEqualTo("BOB"); - assertThat(results.get(1)).isEqualTo("STACY"); - } - - /* - * Target function `class UpperCaseFunction implements Function` - * No Main/Start class present, no Spring configuration - * - * Function class is discovered via 'Function-Class` manifest entry - */ - @Test - public void testNoMainAndNoStartClassAndNoSpringConfigurationDiscoverClassFromManifest() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootjarnostart/target/bootjarnostart-1.0.0.RELEASE-exec.jar" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function function = catalog.lookup("upperCaseFunction"); - - assertThat(function.apply("bob")).isEqualTo("BOB"); - assertThat(function.apply("stacy")).isEqualTo("STACY"); - - Function, Flux> functionAsFlux = catalog.lookup("upperCaseFunction"); - - List results = functionAsFlux.apply(Flux.just("bob", "stacy")).collectList().block(); - assertThat(results.get(0)).isEqualTo("BOB"); - assertThat(results.get(1)).isEqualTo("STACY"); - } - - /* - * Target function: - * - * @Bean public Function uppercase() - */ - @Test - public void testWithMainAndStartClassAndSpringConfiguration() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.definition=uppercase" }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("uppercase", "application/json"); - - Message result = function - .apply(MessageBuilder.withPayload("\"bob\"".getBytes(StandardCharsets.UTF_8)).build()); - assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("\"BOB\""); - } - - @Test - public void testWithLegacyProperties() throws Exception { - String[] args = new String[] { - "--function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar", - "--function.name=uppercase" }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("uppercase", "application/json"); - - Message result = function - .apply(MessageBuilder.withPayload("\"bob\"".getBytes(StandardCharsets.UTF_8)).build()); - assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("\"BOB\""); - } - - /* - * Same as above but: - * Given that Java 11 does not include 'javax' packages, this test simply validates that - * the delegation will be made to archive loader where it is available - */ - @Test - public void testWithMainAndStartClassAndSpringConfigurationJavax() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootapp-with-javax/target/bootapp-with-javax-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-name=uppercase" }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("uppercase", "application/json"); - - Message result = function - .apply(MessageBuilder.withPayload("\"foo@bar.com\"".getBytes(StandardCharsets.UTF_8)).build()); - assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("\"FOO@BAR.COM\""); - } - - /* - * Target function: - * - * @Bean public Function uppercase() - * - * this contains SCF on classpath - */ - @Test - public void testWithMainAndStartClassAndSpringConfigurationAndSCFOnClasspath() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootapp-with-scf/target/bootapp-with-scf-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-name=uppercase" }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("uppercase", "application/json"); - - Message result = function - .apply(MessageBuilder.withPayload("\"bob\"".getBytes(StandardCharsets.UTF_8)).build()); - assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("\"BOB\""); - } - - /* - * Target function: - * - * @Bean public Function uppercasePerson() - */ - @Test - public void testWithMainAndStartClassAndSpringConfigurationAndTypeConversion() throws Exception { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootapp/target/bootapp-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-name=uppercasePerson" }; - - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - Function, Message> function = catalog.lookup("uppercasePerson", "application/json"); - - Message result = function.apply( - MessageBuilder.withPayload("{\"name\":\"bob\",\"id\":1}".getBytes(StandardCharsets.UTF_8)).build()); - assertThat(new String(result.getPayload(), StandardCharsets.UTF_8)).isEqualTo("{\"name\":\"BOB\",\"id\":1}"); - } - - /* - * Target Function - * - * @Bean Function, Flux>, Tuple2, Flux>> - */ - @Test - @Disabled - public void testBootAppWithMultipleInputOutput() { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootapp-multi/target/bootapp-multi-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-name=fn" - }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - Function>, Flux>>, Flux>> multiInputFunction = catalog - .lookup("fn", "application/json"); - - Message carEventMessage = MessageBuilder.withPayload("{\"carEvent\":\"CAR IS BUILT\"}".getBytes()).build(); - Message checkoutEventMessage = MessageBuilder.withPayload("{\"checkoutEvent\":\"CAR IS CHECKED OUT\"}".getBytes()).build(); - Flux> carEventStream = Flux.just(carEventMessage); - Flux> checkoutEventStream = Flux.just(checkoutEventMessage); - - Flux> result = multiInputFunction.apply(Tuples.of(carEventStream, checkoutEventStream)); - - byte[] resutBytes = result.blockFirst().getPayload(); - assertThat(resutBytes).isEqualTo("{\"orderEvent\":\"CartEvent: CAR IS BUILT- CheckoutEvent: CAR IS CHECKED OUT\"}".getBytes()); - } - - /* - * Target Function - * - * Function, Flux>, Tuple2, Flux>> - */ - @Test - @Disabled - public void testBootJarWithMultipleInputOutput() { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootjar-multi/target/bootjar-multi-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-class=function.example.Repeater" - }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - Function>, Flux>>, Tuple2>, Flux>>> function = - catalog.lookup("repeater", "application/json", "application/json"); - - Message msg1 = MessageBuilder.withPayload("\"one\"".getBytes()).build(); - Message msg2 = MessageBuilder.withPayload("\"two\"".getBytes()).build(); - Flux> inputOne = Flux.just(msg1, msg2); - - Message msgInt1 = MessageBuilder.withPayload("\"1\"".getBytes()).build(); - Message msgInt2 = MessageBuilder.withPayload("\"2\"".getBytes()).build(); - Flux> inputTwo = Flux.just(msgInt1, msgInt2); - - Tuple2>, Flux>> result = function.apply(Tuples.of(inputOne, inputTwo)); - List result1 = new ArrayList<>(); - List result2 = new ArrayList<>(); - result.getT1().subscribe(message -> { - result1.add(new String(message.getPayload())); - }); - result.getT2().subscribe(message -> { - result2.add(new String(message.getPayload())); - }); - - assertThat(result1.get(0)).isEqualTo("\"one\""); - assertThat(result1.get(1)).isEqualTo("\"two\""); - - assertThat(result2.get(0)).isEqualTo("3"); - assertThat(result2.get(1)).isEqualTo("2"); - } - - // same as previous test, but lookup is empty - @Test - @Disabled - public void testBootJarWithMultipleInputOutputEmptyLookup() { - String[] args = new String[] { - "--spring.cloud.function.location=target/it/bootjar-multi/target/bootjar-multi-1.0.0.RELEASE-exec.jar", - "--spring.cloud.function.function-class=function.example.Repeater" - }; - ApplicationContext context = SpringApplication.run(DeployerApplication.class, args); - FunctionCatalog catalog = context.getBean(FunctionCatalog.class); - - Function>, Flux>>, Tuple2>, Flux>>> function = - catalog.lookup("", "application/json", "application/json"); - - Message msg1 = MessageBuilder.withPayload("\"one\"".getBytes()).build(); - Message msg2 = MessageBuilder.withPayload("\"two\"".getBytes()).build(); - Flux> inputOne = Flux.just(msg1, msg2); - - Message msgInt1 = MessageBuilder.withPayload("\"1\"".getBytes()).build(); - Message msgInt2 = MessageBuilder.withPayload("\"2\"".getBytes()).build(); - Flux> inputTwo = Flux.just(msgInt1, msgInt2); - - Tuple2>, Flux>> result = function.apply(Tuples.of(inputOne, inputTwo)); - List result1 = new ArrayList<>(); - List result2 = new ArrayList<>(); - result.getT1().subscribe(message -> { - result1.add(new String(message.getPayload())); - }); - result.getT2().subscribe(message -> { - result2.add(new String(message.getPayload())); - }); - - assertThat(result1.get(0)).isEqualTo("\"one\""); - assertThat(result1.get(1)).isEqualTo("\"two\""); - - assertThat(result2.get(0)).isEqualTo("3"); - assertThat(result2.get(1)).isEqualTo("2"); - } - - @SpringBootApplication(proxyBeanMethods = false) - private static class DeployerApplication { - @Bean - public MavenProperties mavenProperties() { - MavenProperties properties = new MavenProperties(); - properties.setLocalRepository("mavenrepo/"); - return properties; - } - } -} diff --git a/spring-cloud-function-integration/pom.xml b/spring-cloud-function-integration/pom.xml deleted file mode 100644 index af51f61b6..000000000 --- a/spring-cloud-function-integration/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - 4.0.0 - - spring-cloud-function-integration - Spring Cloud Function with Spring Integration - Spring Cloud Function with Spring Integration - - - spring-cloud-function-parent - org.springframework.cloud - 4.1.0-SNAPSHOT - - - - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.boot - spring-boot-starter-integration - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.integration - spring-integration-test - test - - - - diff --git a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowAutoConfiguration.java b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowAutoConfiguration.java deleted file mode 100644 index 03d3848ae..000000000 --- a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowAutoConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2023-2023 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.integration.dsl; - -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.context.annotation.Bean; - -/** - * The auto-configuration to expose a {@link FunctionFlowBuilder} bean - * based on the auto-configured {@link FunctionCatalog}. - * - * @author Artem Bilan - * - * @since 4.0.3 - */ -@AutoConfiguration(after = ContextFunctionCatalogAutoConfiguration.class) -public class FunctionFlowAutoConfiguration { - - @Bean - FunctionFlowBuilder functionFlowBuilder(FunctionCatalog functionCatalog) { - return new FunctionFlowBuilder(functionCatalog); - } - -} diff --git a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowBuilder.java b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowBuilder.java deleted file mode 100644 index 1ad83a440..000000000 --- a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowBuilder.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2023-2023 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.integration.dsl; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.reactivestreams.Publisher; - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.integration.core.MessageSource; -import org.springframework.integration.dsl.GatewayProxySpec; -import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.IntegrationFlowBuilder; -import org.springframework.integration.dsl.MessageChannelSpec; -import org.springframework.integration.dsl.MessageProducerSpec; -import org.springframework.integration.dsl.MessageSourceSpec; -import org.springframework.integration.dsl.MessagingGatewaySpec; -import org.springframework.integration.dsl.SourcePollingChannelAdapterSpec; -import org.springframework.integration.endpoint.MessageProducerSupport; -import org.springframework.integration.gateway.MessagingGatewaySupport; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.util.Assert; - -/** - * The entry point for starting a {@link FunctionFlowDefinition}. - * Requires a {@link FunctionCatalog} to lookup function instances - * by their names or definitions from respective operators. - *

- * In addition to standard {@link IntegrationFlow} {@code from()} overloaded methods (for convenience), - * this class introduces {@link #fromSupplier(String)} factory methods to resolve the target {@link Supplier} - * by its name or function definition from the provided {@link FunctionCatalog}. - *

- * This class represents a DSL for functions composition via integration endpoints. - * Extra processing can be done in between functions by the regular {@link IntegrationFlow} operators: - *

- * {@code
- * @Bean
- * IntegrationFlow someFunctionFlow(FunctionFlowBuilder functionFlowBuilder) {
- *		return functionFlowBuilder
- *				.fromSupplier("timeSupplier")
- *				.apply("spelFunction")
- *				.log(LoggingHandler.Level.DEBUG, "some.log.category")
- *				.transform(String::toUpperCase)
- *				.accept("fileConsumer");
- * }
- * }
- * 
- * - * @author Artem Bilan - * - * @since 4.0.3 - */ -public class FunctionFlowBuilder { - - private final FunctionLookupHelper functionLookupHelper; - - public FunctionFlowBuilder(FunctionCatalog functionCatalog) { - Assert.notNull(functionCatalog, "'functionCatalog' must not be null"); - this.functionLookupHelper = new FunctionLookupHelper(functionCatalog); - } - - public FunctionFlowDefinition fromSupplier(String supplierDefinition) { - return fromSupplier(supplierDefinition, null); - } - - public FunctionFlowDefinition fromSupplier(String supplierDefinition, - @Nullable Consumer endpointConfigurer) { - - return fromSupplier(this.functionLookupHelper.lookupSupplier(supplierDefinition), endpointConfigurer); - } - - public FunctionFlowDefinition fromSupplier(Supplier messageSource) { - return fromSupplier(messageSource, null); - } - - public FunctionFlowDefinition fromSupplier(Supplier messageSource, - @Nullable Consumer endpointConfigurer) { - - return toFunctionFlow(IntegrationFlow.fromSupplier(messageSource, endpointConfigurer)); - } - - public FunctionFlowDefinition from(MessageChannel messageChannel) { - return toFunctionFlow(IntegrationFlow.from(messageChannel)); - } - - public FunctionFlowDefinition from(String messageChannelName) { - return from(messageChannelName, false); - } - - public FunctionFlowDefinition from(String messageChannelName, boolean fixedSubscriber) { - return toFunctionFlow(IntegrationFlow.from(messageChannelName, fixedSubscriber)); - } - - public FunctionFlowDefinition from(MessageSourceSpec> messageSourceSpec, - Consumer endpointConfigurer) { - - return toFunctionFlow(IntegrationFlow.from(messageSourceSpec, endpointConfigurer)); - } - - public FunctionFlowDefinition from(MessageSource messageSource) { - return from(messageSource, null); - } - - public FunctionFlowDefinition from(MessageSource messageSource, - @Nullable Consumer endpointConfigurer) { - - return toFunctionFlow(IntegrationFlow.from(messageSource, endpointConfigurer)); - } - - public FunctionFlowDefinition from(MessageProducerSupport messageProducer) { - return toFunctionFlow(IntegrationFlow.from(messageProducer)); - } - - public FunctionFlowDefinition from(MessagingGatewaySupport inboundGateway) { - return toFunctionFlow(IntegrationFlow.from(inboundGateway)); - } - - public FunctionFlowDefinition from(MessageChannelSpec messageChannelSpec) { - return toFunctionFlow(IntegrationFlow.from(messageChannelSpec)); - } - - public FunctionFlowDefinition from(MessageProducerSpec messageProducerSpec) { - return toFunctionFlow(IntegrationFlow.from(messageProducerSpec)); - } - - public FunctionFlowDefinition from(MessageSourceSpec> messageSourceSpec) { - return toFunctionFlow(IntegrationFlow.from(messageSourceSpec)); - } - - public FunctionFlowDefinition from(MessagingGatewaySpec inboundGatewaySpec) { - return toFunctionFlow(IntegrationFlow.from(inboundGatewaySpec)); - } - - public FunctionFlowDefinition from(Class serviceInterface) { - return from(serviceInterface, null); - } - - public FunctionFlowDefinition from(Class serviceInterface, - @Nullable Consumer endpointConfigurer) { - - return toFunctionFlow(IntegrationFlow.from(serviceInterface, endpointConfigurer)); - } - - public FunctionFlowDefinition from(Publisher> publisher) { - return toFunctionFlow(IntegrationFlow.from(publisher)); - } - - private FunctionFlowDefinition toFunctionFlow(IntegrationFlowBuilder from) { - FunctionFlowDefinition functionFlow = new FunctionFlowDefinition(this.functionLookupHelper); - from.channel(functionFlow.getInputChannel()); - functionFlow.addUpstreamComponents(from.get().getIntegrationComponents()); - return functionFlow; - } - -} diff --git a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowDefinition.java b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowDefinition.java deleted file mode 100644 index cc8b84553..000000000 --- a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionFlowDefinition.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2023-2023 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.integration.dsl; - -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.IntegrationFlowExtension; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; - -/** - * The {@link IntegrationFlowExtension} implementation for Spring Cloud Function domain. - * Adds operators for functions and consumers and overloaded versions based on their names - * or definitions resolved from the provided {@link org.springframework.cloud.function.context.FunctionCatalog}. - * - * @author Artem Bilan - * - * @since 4.0.3 - */ -public final class FunctionFlowDefinition extends IntegrationFlowExtension { - - private final FunctionLookupHelper functionLookupHelper; - - FunctionFlowDefinition(FunctionLookupHelper functionLookupHelper) { - this.functionLookupHelper = functionLookupHelper; - } - - MessageChannel getInputChannel() { - return getCurrentMessageChannel(); - } - - void addUpstreamComponents(Map components) { - addComponents(components); - } - - /** - * Configure a {@link org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper} - * as a handler in the endpoint by its definition from the - * {@link org.springframework.cloud.function.context.FunctionCatalog}. - * @param functionDefinition the function definition in the function catalog. - * @return the current flow builder. - */ - public FunctionFlowDefinition apply(String functionDefinition) { - return apply(this.functionLookupHelper.lookupFunction(functionDefinition)); - } - - /** - * Configure a {@link Function} as a handler in the endpoint. - * @param function the {@link Function} to use. - * @return the current flow builder. - */ - public FunctionFlowDefinition apply(Function, ?> function) { - return handle(Message.class, (message, headers) -> function.apply(message)); - } - - /** - * Configure a {@link org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper} - * as a one-way handler in the final endpoint by its definition from the - * {@link org.springframework.cloud.function.context.FunctionCatalog}. - * @param consumerDefinition the consumer definition in the function catalog. - * @return the current flow builder. - */ - public IntegrationFlow accept(String consumerDefinition) { - return accept(this.functionLookupHelper.lookupConsumer(consumerDefinition)); - } - - /** - * Configure a {@link Consumer} as a one-way handler in the final endpoint. - * @param consumer the {@link Consumer} to use. - * @return the current flow builder. - */ - public IntegrationFlow accept(Consumer> consumer) { - return handle(consumer::accept) - .get(); - } - -} diff --git a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java b/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java deleted file mode 100644 index 262ee1f5e..000000000 --- a/spring-cloud-function-integration/src/main/java/org/springframework/cloud/function/integration/dsl/FunctionLookupHelper.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2023-2023 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.integration.dsl; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.util.Assert; - -/** - * The helper class to lookup functions from the catalog in lazy manner and cache their instances. - * - * @author Artem Bilan - * - * @since 4.0.3 - */ -public class FunctionLookupHelper { - - private final FunctionCatalog functionCatalog; - - FunctionLookupHelper(FunctionCatalog functionCatalog) { - this.functionCatalog = functionCatalog; - } - -

Supplier

lookupSupplier(String functionDefinition) { - Supplier> memoizedSupplier = lazyLookup(Supplier.class, functionDefinition); - return () -> memoizedSupplier.get().get(); - } - -

Function lookupFunction(String functionDefinition) { - Supplier> memoizedFunction = lazyLookup(Function.class, functionDefinition); - return (p) -> memoizedFunction.get().apply(p); - } - -

Consumer

lookupConsumer(String consumerDefinition) { - Supplier> memoizedConsumer = lazyLookup(Consumer.class, consumerDefinition); - return (p) -> memoizedConsumer.get().accept(p); - } - - private Supplier lazyLookup(Class functionType, String functionDefinition) { - return memoize(() -> requireNonNull(functionType, functionDefinition)); - } - - private T requireNonNull(Class functionType, String functionDefinition) { - T function = this.functionCatalog.lookup(functionType, functionDefinition); - Assert.notNull(function, () -> "No '" + functionDefinition + "' in the catalog"); - return function; - } - - /** - * The delegate {@link Supplier#get()} is called exactly once and the result is cached. - * @param Generic type of supplied value - * @param delegate The actual Supplier - * @return The memoized Supplier - */ - private static Supplier memoize(Supplier delegate) { - AtomicReference value = new AtomicReference<>(); - return () -> { - T val = value.get(); - if (val == null) { - synchronized (value) { - val = value.get(); - if (val == null) { - val = delegate.get(); - value.set(val); - } - } - } - return val; - }; - } - -} diff --git a/spring-cloud-function-integration/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-integration/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index b7d39cea2..000000000 --- a/spring-cloud-function-integration/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.springframework.cloud.function.integration.dsl.FunctionFlowAutoConfiguration diff --git a/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java b/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java deleted file mode 100644 index e4ee38a2b..000000000 --- a/spring-cloud-function-integration/src/test/java/org/springframework/cloud/function/integration/dsl/FunctionFlowTests.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2023-2023 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.integration.dsl; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.integration.channel.QueueChannel; -import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.PollerSpec; -import org.springframework.integration.dsl.Pollers; -import org.springframework.integration.dsl.context.IntegrationFlowContext; -import org.springframework.integration.endpoint.SourcePollingChannelAdapter; -import org.springframework.integration.handler.LoggingHandler; -import org.springframework.integration.scheduling.PollerMetadata; -import org.springframework.integration.test.util.OnlyOnceTrigger; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageDeliveryException; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.annotation.DirtiesContext; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * @author Artem Bilan - * - * @since 4.0.3 - */ -@SpringBootTest -@DirtiesContext -public class FunctionFlowTests { - - // To verify cached lookups - @SpyBean - FunctionCatalog functionCatalog; - - @Autowired - BlockingQueue results; - - @Test - void fromSupplierOverFunctionToConsumer(@Autowired SourcePollingChannelAdapter supplierEndpoint, - @Autowired QueueChannel wireTapChannel) throws InterruptedException { - - supplierEndpoint.start(); - - String result = this.results.poll(10, TimeUnit.SECONDS); - assertThat(result).isEqualTo("SIMPLE TEST DATA"); - Message receive = wireTapChannel.receive(10_000); - assertThat(receive) - .extracting(Message::getPayload) - .isEqualTo("simple test data".getBytes()); - - supplierEndpoint.stop(); - } - - @Test - void fromChannelToFunctionComposition(@Autowired MessageChannel functionCompositionInput) - throws InterruptedException { - - functionCompositionInput.send(new GenericMessage<>("compose this")); - - String result = this.results.poll(10, TimeUnit.SECONDS); - assertThat(result).isEqualTo("COMPOSE THIS"); - - functionCompositionInput.send(new GenericMessage<>("compose again")); - - result = this.results.poll(10, TimeUnit.SECONDS); - assertThat(result).isEqualTo("COMPOSE AGAIN"); - - // Ensure that FunctionLookupHelper.memoize() does its trick calling FunctionCatalog.lookup() only once - verify(this.functionCatalog).lookup(Consumer.class, "upperCaseFunction|simpleStringConsumer"); - } - - @Test - void noFunctionInCatalogException(@Autowired IntegrationFlowContext integrationFlowContext) { - // We need to mock here since BeanFactoryAwareFunctionRegistry will have slightly different logic - FunctionCatalog mockFunctionCatalog = mock(FunctionCatalog.class); - - FunctionFlowBuilder functionFlowBuilder = new FunctionFlowBuilder(mockFunctionCatalog); - - IntegrationFlow wrongFlow = - functionFlowBuilder.from("inputChannel") - .accept("nonExistingConsumer"); - - IntegrationFlowContext.IntegrationFlowRegistration registration = - integrationFlowContext.registration(wrongFlow) - .register(); - - assertThatExceptionOfType(MessageDeliveryException.class) - .isThrownBy(() -> registration.getInputChannel().send(new GenericMessage<>("test"))) - .withRootCauseInstanceOf(IllegalArgumentException.class) - .withStackTraceContaining("No 'nonExistingConsumer' in the catalog"); - - registration.destroy(); - } - - - @EnableAutoConfiguration - @Configuration(proxyBeanMethods = false) - static class TestIntegrationConfiguration { - - @Bean(PollerMetadata.DEFAULT_POLLER) - PollerSpec defaultPoller() { - return Pollers.trigger(new OnlyOnceTrigger()); - } - - @Bean - Supplier simpleByteArraySupplier() { - return "simple test data"::getBytes; - } - - @Bean - Function upperCaseFunction() { - return String::toUpperCase; - } - - @Bean - BlockingQueue results() { - return new LinkedBlockingQueue<>(); - } - - @Bean - Consumer simpleStringConsumer(BlockingQueue results) { - return results::add; - } - - @Bean - QueueChannel wireTapChannel() { - return new QueueChannel(); - } - - @Bean - IntegrationFlow someFunctionFlow(FunctionFlowBuilder functionFlowBuilder) { - return functionFlowBuilder - .fromSupplier("simpleByteArraySupplier", e -> e.id("supplierEndpoint").autoStartup(false)) - .wireTap("wireTapChannel") - .apply("upperCaseFunction") - .log(LoggingHandler.Level.WARN, FunctionFlowTests.class.getName()) - .accept("simpleStringConsumer"); - } - - @Bean - IntegrationFlow functionCompositionFlow(FunctionFlowBuilder functionFlowBuilder) { - return functionFlowBuilder - .from("functionCompositionInput") - .accept("upperCaseFunction|simpleStringConsumer"); - } - - } - -} diff --git a/spring-cloud-function-kotlin/.jdk8 b/spring-cloud-function-kotlin/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-kotlin/README.adoc b/spring-cloud-function-kotlin/README.adoc deleted file mode 100644 index e76a1c926..000000000 --- a/spring-cloud-function-kotlin/README.adoc +++ /dev/null @@ -1,4 +0,0 @@ -!!! INTERNAL !!! - -Contains only Kotlin tests. -Since version 3.1.3, user's should not be declaring explicit dependency on this module. \ No newline at end of file diff --git a/spring-cloud-function-kotlin/pom.xml b/spring-cloud-function-kotlin/pom.xml deleted file mode 100644 index 1f42e42a4..000000000 --- a/spring-cloud-function-kotlin/pom.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-kotlin - jar - Spring Cloud Function Kotlin Support - Spring Cloud Function Kotlin Support - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - com.amazonaws - aws-lambda-java-events - 3.9.0 - provided - - - com.amazonaws - aws-lambda-java-core - 1.2.1 - provided - - - com.amazonaws - aws-lambda-java-serialization - 1.0.0 - provided - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlinx - kotlinx-coroutines-reactor - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.cloud - spring-cloud-function-web - test - - - org.springframework - spring-webflux - test - - - org.springframework.boot - spring-boot-starter-web - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - kotlin-maven-plugin - org.jetbrains.kotlin - - - test-compile - - test-compile - - - - ${project.basedir}/src/test/kotlin - ${project.basedir}/src/test/java - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - - - diff --git a/spring-cloud-function-kotlin/src/main/resources/META-INF/spring.factories b/spring-cloud-function-kotlin/src/main/resources/META-INF/spring.factories deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinSuspendTests.java b/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinSuspendTests.java deleted file mode 100644 index 874de12a4..000000000 --- a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinSuspendTests.java +++ /dev/null @@ -1,77 +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.kotlin; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; - -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.support.GenericApplicationContext; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Adrien Poupard - */ -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class ContextFunctionCatalogAutoConfigurationKotlinSuspendTests { - - private GenericApplicationContext context; - - private FunctionCatalog catalog; - - @AfterEach - public void close() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void typeDiscoveryTests() { - create(new Class[] { KotlinSuspendFlowLambdasConfiguration.class, - ContextFunctionCatalogAutoConfigurationKotlinTests.SimpleConfiguration.class }); - - FunctionCatalog functionCatalog = this.context.getBean(FunctionCatalog.class); - - FunctionInvocationWrapper kotlinFunction = functionCatalog.lookup("kotlinFunction"); - assertThat(kotlinFunction.isFunction()).isTrue(); - assertThat(kotlinFunction.getInputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - assertThat(kotlinFunction.getOutputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - - FunctionInvocationWrapper kotlinConsumer = functionCatalog.lookup("kotlinConsumer"); - assertThat(kotlinConsumer.isConsumer()).isTrue(); - assertThat(kotlinConsumer.getInputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - - FunctionInvocationWrapper kotlinSupplier = functionCatalog.lookup("kotlinSupplier"); - assertThat(kotlinSupplier.isSupplier()).isTrue(); - assertThat(kotlinSupplier.getOutputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - - FunctionInvocationWrapper kotlinPojoFunction = functionCatalog.lookup("kotlinPojoFunction"); - assertThat(kotlinPojoFunction.isFunction()).isTrue(); - assertThat(kotlinPojoFunction.getInputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - assertThat(kotlinPojoFunction.getOutputType().getTypeName()).isEqualTo("reactor.core.publisher.Flux"); - } - - private void create(Class[] types, String... props) { - this.context = (GenericApplicationContext) new SpringApplicationBuilder(types).properties(props).run(); - this.catalog = this.context.getBean(FunctionCatalog.class); - } -} diff --git a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java b/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java deleted file mode 100644 index 5954bf4c8..000000000 --- a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java +++ /dev/null @@ -1,173 +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.kotlin; - -import java.util.function.Function; -import java.util.function.Supplier; - -import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -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.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - */ -public class ContextFunctionCatalogAutoConfigurationKotlinTests { - - private GenericApplicationContext context; - - private FunctionCatalog catalog; - - @AfterEach - public void close() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void typeDiscoveryTests() { - create(new Class[] { KotlinLambdasConfiguration.class, - SimpleConfiguration.class, - KotlinComponentFunction.class, - ComponentUppercase.class}); - - FunctionCatalog functionCatalog = this.context.getBean(FunctionCatalog.class); - - FunctionInvocationWrapper kotlinComponentFunction = functionCatalog.lookup("kotlinComponentFunction"); - assertThat(kotlinComponentFunction.isFunction()).isTrue(); - assertThat(kotlinComponentFunction.getInputType().getTypeName()).isEqualTo("java.lang.String"); - assertThat(kotlinComponentFunction.getOutputType().getTypeName()).isEqualTo("java.lang.String"); - assertThat(kotlinComponentFunction.apply("bob")).isEqualTo("BOB"); - - FunctionInvocationWrapper kotlinFunction = functionCatalog.lookup("kotlinFunction"); - assertThat(kotlinFunction.isFunction()).isTrue(); - assertThat(kotlinFunction.getInputType()).isEqualTo(String.class); - assertThat(kotlinFunction.getOutputType()).isEqualTo(String.class); - - FunctionInvocationWrapper kotlinConsumer = functionCatalog.lookup("kotlinConsumer"); - assertThat(kotlinConsumer.isConsumer()).isTrue(); - assertThat(kotlinConsumer.getInputType()).isEqualTo(String.class); - - FunctionInvocationWrapper kotlinSupplier = functionCatalog.lookup("kotlinSupplier"); - assertThat(kotlinSupplier.isSupplier()).isTrue(); - assertThat(kotlinSupplier.getOutputType()).isEqualTo(String.class); - - FunctionInvocationWrapper kotlinPojoFunction = functionCatalog.lookup("kotlinPojoFunction"); - assertThat(kotlinPojoFunction.isFunction()).isTrue(); - assertThat(kotlinPojoFunction.getInputType()).isEqualTo(Person.class); - assertThat(kotlinPojoFunction.getOutputType()).isEqualTo(String.class); - - FunctionInvocationWrapper kotlinListPojoFunction = functionCatalog.lookup("kotlinListPojoFunction"); - assertThat(kotlinListPojoFunction.isFunction()).isTrue(); - assertThat(kotlinListPojoFunction.getInputType().getTypeName()).isEqualTo("java.util.List"); - assertThat(kotlinListPojoFunction.getOutputType()).isEqualTo(String.class); - - FunctionInvocationWrapper componentUppercase = functionCatalog.lookup("componentUppercase"); - assertThat(componentUppercase.isFunction()).isTrue(); - assertThat(componentUppercase.getInputType()).isEqualTo(String.class); - assertThat(componentUppercase.getOutputType()).isEqualTo(String.class); - - assertThat(componentUppercase.apply("hello")).isEqualTo("HELLO"); - - FunctionInvocationWrapper uppercaseBean = functionCatalog.lookup("uppercase"); - assertThat(uppercaseBean.isFunction()).isTrue(); - assertThat(uppercaseBean.getInputType()).isEqualTo(String.class); - assertThat(uppercaseBean.getOutputType()).isEqualTo(String.class); - - assertThat(uppercaseBean.apply("hello")).isEqualTo("HELLO"); - } - - @Test - public void testWithComplexTypesAndRouting() { - create(new Class[] { KotlinLambdasConfiguration.class, - SimpleConfiguration.class }); - - FunctionInvocationWrapper function = this.catalog.lookup("kotlinListPojoFunction"); - String result = (String) function.apply("[{\"name\":\"Ricky\"}]"); - assertThat(result).isEqualTo("List of: Ricky"); - - function = this.catalog.lookup(Function.class, "functionRouter"); - result = (String) function.apply(MessageBuilder.withPayload("[{\"name\":\"Ricky\"}]") - .setHeader("spring.cloud.function.definition", "kotlinListPojoFunction").build()); - assertThat(result).isEqualTo("List of: Ricky"); - - } - - @Test - public void kotlinLambdas() { - create(new Class[] { KotlinLambdasConfiguration.class, - SimpleConfiguration.class }); - - assertThat(this.context.getBean("kotlinFunction")).isInstanceOf(Function1.class); - FunctionInvocationWrapper function = this.catalog.lookup(Function.class, "kotlinFunction"); - assertThat(function).isInstanceOf(Function.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(function.getInputType()))).isAssignableFrom(String.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(function.getOutputType()))).isAssignableFrom(String.class); - - - function = this.catalog.lookup(Function.class, "kotlinConsumer"); - assertThat(this.context.getBean("kotlinConsumer")).isInstanceOf(Function1.class); - assertThat(function).isInstanceOf(Function.class); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(function.getInputType()))).isAssignableFrom(String.class); - - - assertThat(this.context.getBean("kotlinSupplier")).isInstanceOf(Function0.class); - FunctionInvocationWrapper supplier = this.catalog.lookup(Function.class, "kotlinSupplier"); - assertThat(supplier).isInstanceOf(Supplier.class); - assertThat(supplier.get()).isEqualTo("Hello"); - assertThat(FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(supplier.getOutputType()))).isAssignableFrom(String.class); - - function = this.catalog.lookup(Function.class, "kotlinFunction|function2"); - assertThat(function.apply("Hello")).isEqualTo("HELLOfunction2"); - - Function javaFunction = this.catalog - .lookup(Function.class, "javaFunction"); - assertThat(javaFunction.apply("Hello")) - .isEqualTo("Hello"); - } - - private void create(Class[] types, String... props) { - this.context = (GenericApplicationContext) new SpringApplicationBuilder(types).properties(props).run(); - this.catalog = this.context.getBean(FunctionCatalog.class); - } - - @EnableAutoConfiguration - @Configuration - protected static class SimpleConfiguration { - - @Bean - public Function function2() { - return value -> value + "function2"; - } - - } - -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/ComponentUppercase.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/ComponentUppercase.kt deleted file mode 100644 index 574b6aa48..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/ComponentUppercase.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.springframework.cloud.function.kotlin - -import org.springframework.stereotype.Component - -@Component -class ComponentUppercase : (String) -> String { - override fun invoke(p1: String): String { - return p1.uppercase() - } -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinComponentFunction.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinComponentFunction.kt deleted file mode 100644 index 629f981ff..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinComponentFunction.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.springframework.cloud.function.kotlin - -import org.springframework.stereotype.Component -import java.util.function.Function - -@Component -class KotlinComponentFunction : Function { - - override fun apply(t: String): String { - return t.uppercase(); - } -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt deleted file mode 100644 index a324131fc..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020-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.kotlin - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import java.util.function.Function -import java.util.List - -/** - * @author Oleg Zhurakousky - * - */ -@EnableAutoConfiguration -@Configuration -open class KotlinLambdasConfiguration { - - @Bean - open fun uppercase(): Function = KotlinComponentFunction() - @Bean - open fun kotlinFunction(): (String) -> String { - return { it.toUpperCase() } - } - - @Bean - open fun kotlinPojoFunction(): (Person) -> String { - return { it.name.toString()} - } - - @Bean - open fun kotlinListPojoFunction(): (List) -> String { - return { - "List of: " + it.get(0).name - } - } - - @Bean - open fun kotlinConsumer(): (String) -> Unit { - return { println(it) } - } - - @Bean - open fun kotlinSupplier(): () -> String { - return { "Hello" } - } - - @Bean - open fun javaFunction(): Function { - return Function { x -> x } - } - -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendFlowLambdasConfiguration.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendFlowLambdasConfiguration.kt deleted file mode 100644 index bfa7e3102..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendFlowLambdasConfiguration.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2021-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.kotlin - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import reactor.core.publisher.Flux -import java.util.function.Function - -/** - * @author Adrien Poupard - * - */ -@EnableAutoConfiguration -@Configuration -open class KotlinSuspendFlowLambdasConfiguration { - - @Bean - open fun kotlinFunction(): suspend (Flow) -> Flow = { flow -> - flow.map { value -> value.toUpperCase() } - } - - @Bean - open fun kotlinPojoFunction(): suspend (Flow) -> Flow = { flow -> - flow.map(Person::toString) - } - - @Bean - open fun kotlinConsumer(): suspend (Flow) -> Unit = { flow -> - flow.collect(::println) - } - - @Bean - open fun kotlinSupplier(): suspend () -> Flow = { - flow { - emit("Hello") - } - } - - @Bean - open fun javaFunction(): Function, Flux> { - return Function { x -> x } - } - -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendLambdasConfiguration.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendLambdasConfiguration.kt deleted file mode 100644 index 68e985550..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinSuspendLambdasConfiguration.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021-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.kotlin - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -/** - * @author Adrien Poupard - * - */ -@EnableAutoConfiguration -@Configuration -open class KotlinSuspendLambdasConfiguration { - - @Bean - open fun kotlinFunction(): suspend (Person) -> String { - return { it.name.toString()} - } - - @Bean - open fun kotlinConsumer(): suspend (String) -> Unit { - return { println(it) } - } - - @Bean - open fun kotlinSupplier(): suspend () -> String { - return { "Hello" } - } - -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt deleted file mode 100644 index f46fb3278..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2020-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.kotlin - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import java.util.function.Function - -/** - * @author Oleg Zhurakousky - * - */ -class Person { - - var name:String? = null; - - -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/AwsKotlinTestsTests.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/AwsKotlinTestsTests.kt deleted file mode 100644 index 36eafbbe3..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/AwsKotlinTestsTests.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2020-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.kotlin.aws - -import org.junit.jupiter.api.Test -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.cloud.function.adapter.aws.FunctionInvoker -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream - -/** - * @author Oleg Zhurakousky - */ -//@SpringBootTest() -//@ContextConfiguration(classes = [RestApplication::class, AwsKotlinTestsTests.TestConfiguration::class]) -open class AwsKotlinTestsTests { - var dynamoDbEvent:String = "{\n" + - " \"Records\": [\n" + - " {\n" + - " \"eventID\": \"dc1e145db718184b1c809f989335b168\",\n" + - " \"eventName\": \"INSERT\",\n" + - " \"eventVersion\": \"1.1\",\n" + - " \"eventSource\": \"aws:dynamodb\",\n" + - " \"awsRegion\": \"eu-central-1\",\n" + - " \"dynamodb\": {\n" + - " \"ApproximateCreationDateTime\": 1.689335433E9,\n" + - " \"Keys\": {\n" + - " \"version\": {\n" + - " \"N\": \"1\"\n" + - " },\n" + - " \"urlPath\": {\n" + - " \"S\": \"image/6037/2023/07/14/1d058d91-c9db-4c6a-aadf-4ab749de95d1.jpg\"\n" + - " }\n" + - " },\n" + - " \"NewImage\": {\n" + - " \"createdAt\": {\n" + - " \"N\": \"1689335427\"\n" + - " },\n" + - " \"provider\": {\n" + - " \"S\": \"XXXXXX\"\n" + - " },\n" + - " \"urlPath\": {\n" + - " \"S\": \"image/6037/2023/07/14/1d058d91-c9db-4c6a-aadf-4ab749de95d1.jpg\"\n" + - " },\n" + - " \"version\": {\n" + - " \"N\": \"1\"\n" + - " },\n" + - " \"status\": {\n" + - " \"S\": \"SUCCESS\"\n" + - " }\n" + - " },\n" + - " \"SequenceNumber\": \"1049234200000000032682603273\",\n" + - " \"SizeBytes\": 7869,\n" + - " \"StreamViewType\": \"NEW_IMAGE\"\n" + - " },\n" + - " \"eventSourceARN\": \"arn:aws:dynamodb:eu-central-1:xxxxxxx:table/example-results/stream/2022-12-06T16:23:45.860\"\n" + - " }\n" + - " ]\n" + - "}" - - @Test - open fun testDynamoDb() { - System.setProperty("MAIN_CLASS", KotlinAwsLambdasConfiguration::class.java.getName()) - System.setProperty("spring.cloud.function.definition", "handleDynamoDbEvent") - var invoker = FunctionInvoker() - - var targetStream = ByteArrayInputStream(this.dynamoDbEvent.toByteArray()) - var output = ByteArrayOutputStream() - invoker.handleRequest(targetStream, output, null) - } -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/KotlinAwsLambdasConfiguration.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/KotlinAwsLambdasConfiguration.kt deleted file mode 100644 index 315c1b63a..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/aws/KotlinAwsLambdasConfiguration.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021-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.kotlin.aws - -import com.amazonaws.services.lambda.runtime.events.DynamodbEvent -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.messaging.Message -import reactor.core.publisher.Flux -import java.util.function.Function - -/** - * @author Adrien Poupard - * - */ -@EnableAutoConfiguration -@Configuration -open class KotlinAwsLambdasConfiguration { - - @Bean - open fun handleDynamoDbEvent(): (Message) -> Unit { - return { println(it) } - } -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageSuspendTests.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageSuspendTests.kt deleted file mode 100644 index 85ad7f68f..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageSuspendTests.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2021-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.kotlin.web - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import org.assertj.core.api.Assertions -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment -import org.springframework.boot.test.web.client.TestRestTemplate -import org.springframework.cloud.function.web.RestApplication -import org.springframework.context.annotation.Bean -import org.springframework.http.MediaType -import org.springframework.http.RequestEntity -import org.springframework.messaging.Message -import org.springframework.messaging.support.MessageBuilder -import org.springframework.test.context.ContextConfiguration -import java.net.URI - -/** - * @author Adrien Poupard - */ -@SpringBootTest( - webEnvironment = WebEnvironment.RANDOM_PORT, - properties = ["spring.cloud.function.web.path=/functions", "spring.main.web-application-type=reactive"] -) -@ContextConfiguration(classes = [RestApplication::class, HeadersToMessageSuspendTests.TestConfiguration::class]) -open class HeadersToMessageSuspendTests { - @Autowired - private val rest: TestRestTemplate? = null - @Test - @Throws(Exception::class) - open fun testBodyAndCustomHeaderFromMessagePropagation() { - // test POJO paylod - var postForEntity = rest!! - .exchange( - RequestEntity.post(URI("/functions/employeeSuspend")) - .contentType(MediaType.APPLICATION_JSON) - .body("[{\"name\":\"Bob\",\"age\":25}]"), String::class.java - ) - - Assertions.assertThat(postForEntity.body).isEqualTo("[{\"name\":\"Bob\",\"age\":25}]") - Assertions.assertThat(postForEntity.headers.containsKey("x-content-type")).isTrue - Assertions.assertThat(postForEntity.headers["x-content-type"]!![0]) - .isEqualTo("application/xml") - Assertions.assertThat(postForEntity.headers["foo"]!![0]).isEqualTo("bar") - - // test simple type payload - postForEntity = rest.postForEntity( - URI("/functions/stringSuspend"), - "HELLO", String::class.java - ) - Assertions.assertThat(postForEntity.body).isEqualTo("[\"HELLO\"]") - Assertions.assertThat(postForEntity.headers.containsKey("x-content-type")).isTrue - Assertions.assertThat(postForEntity.headers["x-content-type"]!![0]) - .isEqualTo("application/xml") - Assertions.assertThat(postForEntity.headers["foo"]!![0]).isEqualTo("bar") - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - open class TestConfiguration { - @Bean("stringSuspend") - open fun functiono():suspend (employee: Flow>) -> Flow> = { flow: Flow> -> - flow.map { request -> - val message = - MessageBuilder.withPayload(request.payload) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build() - message - } - } - - @Bean("employeeSuspend") - open fun function1(): suspend (employee: Flow>) -> Flow> = { flow -> - flow.map { request -> - val message = - MessageBuilder - .withPayload(request.payload) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar") - .build() - message - } - } - } - - open class Employee { - var name: String? = null - var age = 0 - } -} diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageTests.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageTests.kt deleted file mode 100644 index 02f1c170d..000000000 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/web/HeadersToMessageTests.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2020-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.kotlin.web - -import org.assertj.core.api.Assertions -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment -import org.springframework.boot.test.web.client.TestRestTemplate -import org.springframework.cloud.function.web.RestApplication -import org.springframework.context.annotation.Bean -import org.springframework.http.MediaType -import org.springframework.http.RequestEntity -import org.springframework.messaging.Message -import org.springframework.messaging.support.MessageBuilder -import org.springframework.test.context.ContextConfiguration -import java.lang.Exception -import java.net.URI - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -@SpringBootTest( - webEnvironment = WebEnvironment.RANDOM_PORT, - properties = ["spring.cloud.function.web.path=/functions", "spring.main.web-application-type=reactive"] -) -@ContextConfiguration(classes = [RestApplication::class, HeadersToMessageTests.TestConfiguration::class]) -open class HeadersToMessageTests { - @Autowired - private val rest: TestRestTemplate? = null - @Test - @Throws(Exception::class) - open fun testBodyAndCustomHeaderFromMessagePropagation() { - // test POJO paylod - var postForEntity = rest!! - .exchange( - RequestEntity.post(URI("/functions/employee")) - .contentType(MediaType.APPLICATION_JSON) - .body("{\"name\":\"Bob\",\"age\":25}"), String::class.java - ) - Assertions.assertThat(postForEntity.body).isEqualTo("{\"name\":\"Bob\",\"age\":25}") - Assertions.assertThat(postForEntity.headers.containsKey("x-content-type")).isTrue - Assertions.assertThat(postForEntity.headers["x-content-type"]!![0]) - .isEqualTo("application/xml") - Assertions.assertThat(postForEntity.headers["foo"]!![0]).isEqualTo("bar") - - // test simple type payload - postForEntity = rest.postForEntity( - URI("/functions/string"), - "{\"name\":\"Bob\",\"age\":25}", String::class.java - ) - Assertions.assertThat(postForEntity.body).isEqualTo("{\"name\":\"Bob\",\"age\":25}") - Assertions.assertThat(postForEntity.headers.containsKey("x-content-type")).isTrue - Assertions.assertThat(postForEntity.headers["x-content-type"]!![0]) - .isEqualTo("application/xml") - Assertions.assertThat(postForEntity.headers["foo"]!![0]).isEqualTo("bar") - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - open class TestConfiguration { - @Bean("string") - open fun functiono(): (message: Message) -> Message = { request: Message -> - val message = - MessageBuilder.withPayload(request.payload) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build() - message - } - - @Bean("employee") - open fun function1(): (employee: Message) -> Message = { request -> - val message = - MessageBuilder - .withPayload(request.payload) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build() - message - } - } - - // used by json converter - open class Employee { - var name: String? = null - var age = 0 - } -} diff --git a/spring-cloud-function-rsocket/.jdk8 b/spring-cloud-function-rsocket/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-rsocket/NOTES.txt b/spring-cloud-function-rsocket/NOTES.txt deleted file mode 100644 index 60f6788f7..000000000 --- a/spring-cloud-function-rsocket/NOTES.txt +++ /dev/null @@ -1,7 +0,0 @@ - -spring.cloud.function.rsocket.bind-address=localhost -spring.cloud.function.rsocket.bind-port=1234 - -spring.cloud.function.rsocket.target-address=localhost -spring.cloud.function.rsocket.target-port=1235 - diff --git a/spring-cloud-function-rsocket/README.md b/spring-cloud-function-rsocket/README.md deleted file mode 100644 index aad21631b..000000000 --- a/spring-cloud-function-rsocket/README.md +++ /dev/null @@ -1,99 +0,0 @@ -### Introduction - -Spring Cloud Function allows you to invoke function via [RSocket](https://rsocket.io/). While you can read more about RSocket and it’s java -implementation [here](https://github.com/rsocket/rsocket-java), this section will describe the parts relevant to Spring Cloud Function integration. - -### Programming model -From the user perspective bringing RSocket does not change the implementation of functions or any of its features, such as type conversion, -composition, POJO functions etc. -And while RSocket allows first class reactive interaction over the network supporting important reactive features such as back pressure, -users of Spring Cloud Function still have freedom to implement their business logic using reactive or imperative functions delegating any -adjustment needed to apply proper invocation model to the framework. - -To use RSocket integration all you need is to add `spring-cloud-function-rsocket` dependency to your classpath -``` - - org.springframework.cloud - spring-cloud-function-rsocket - -``` - -To interact with functions via RSocket we rely on Spring Boot support for RSocket and `RSocketRequester.Builder` API. -The code below shows the key parts and you can get more details on various interaction models -from [this test case](https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java). - - -``` -@Bean -public Function uppercase() { - return v -> v.toUpperCase(); -} - -. . . - -RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - -rsocketRequesterBuilder.tcp("localhost", port) - .route(“uppercase") - .data("\"hello\"") - .retrieveMono(String.class) - .subscribe(System.out::println); -``` - -Once connected to RSocket we use `route` operation to specify which function we want to invoke providing the actual -payload via `data` operation. Then we use one of the `retrieve` operations that best suits our desired interaction -(RSocket supports multiple interaction models such as fire-and-forget, request-reply etc.) - -#### Order of priority for routing instructions - -As you can see from the preceding examples, we provide function definition as a value to `route(..)` operator of `RSocketRequester.Builder`. -However that is not the only way. You can also use standard `spring.cloud.function.definition` property as well as `spring.cloud.function.routing-expression` or property or `MessageRoutingCallback` on the server side of the RSocket interaction (see "Function Routing and Filtering" section of reference manual). -This raises a question of _order_ and _priorities_ when it comes to reconsiling a conflict in the event several ways of providing definition are used. So it is a mater of clearly stating the rule which is: - -***1 - MessageRoutingCallback*** -The `MessageRoutingCallback` takes precedence over all other ways of providing function definition resolution. - -***2 - spring.cloud.function.routing-expression*** -The `spring.cloud.function.routing-expression` property takes next precedence. So, in the event you may have also use `route(..)` operator or `spring.cloud.function.definition` property, they will be ignored if `spring.cloud.function.routing-expression` property is provided. - -***3 - route(..)*** -The next in line is `route(..)` operator. So in the event there are no `spring.cloud.function.routing-expression` property but you defined `spring.cloud.function.definition` property, it will be ignored in favor of definition provided by the `route(..)` operator. - -***4 - spring.cloud.function.definition*** -The `spring.cloud.function.definition` property is the last in the list allowing you to simply `route("")` to empty string. - - -### Messaging - -If you want to provide and/or receive additional information that you would normally communicate via Message headers you can send and receive Spring `Message`. -For example, the following tests case demonstrates how you can accomplish that. -``` -Person p = new Person(); -p.setName("Ricky"); -Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - -Message result = rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(message) - .retrieveMono(new ParameterizedTypeReference>() {}) - .block(); -``` -Aside from sending `Message`, note the usage of `ParameterizedTypeReference` to specify that we want not only `Message` in return but also `Message` with specific payload type. - -### Function Composition over RSocket (Distributed Function Composition) - -By now you shoudl be familiar with the standard function composition feature (e.g., `functionA|functionB|functionC`). This feature allows you to compose several co-located functions into one. But what if these functions are not co-located and instead separated by the network? - -With RSocket and our _distributed function composition_ feature you can still do it. So let's look at the example. - -Let's say we have `uppercase` function available to you locally and `reverse` function exposed via separate RSocket and you wan to compose `uppercase` and `reverse` into a single function. Had they been both available locally it would have been as simple as `uppercase|reverse`, but given that `reverse` function is not locally available we need a way to specify that in our composition instruction. For that we're using _redirect_ operator. So it woudl look like this `uppercase>localhost:2222`, where `localhost:2222` is the host/port combination where `reverse` function is hosted. -What's interesting is that remote function can in itself be a result of function composition (local or remote), so effectively you are composing `uppercase` with whatever function definition (which could be composition) that is running on `localhost:2222`. - -The complete example is available in [this test case](https://github.com/spring-cloud/spring-cloud-function/blob/0e3a27a392f5c69727d909db26c2ba6aa0344cfd/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java#L371). -And as you can see it is a bit more complex to showcase this feature. In this test we are composing `reverse` function with `uppercase|concat` function running remotely and then with `wrap` function running locally as if `reverse|uppercase|concat|wrap`. -So you can see `--spring.cloud.function.definition=reverse>localhost:" + portA + "|wrap"` where `localhost:" + portA` points to another application context instance with `--spring.cloud.function.definition=uppercase|concat`. The result of the `reverse` function are sent to `uppercase|concat` function via RSocket and the result of that are fed into `wrap` function. - -### Samples - -You can also look at one of the [RSocket samples](https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-cloudevent-rsocket) that is also introduces you to Cloud Events diff --git a/spring-cloud-function-rsocket/pom.xml b/spring-cloud-function-rsocket/pom.xml deleted file mode 100644 index 9b238e2b7..000000000 --- a/spring-cloud-function-rsocket/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-rsocket - jar - Spring Cloud Function RSocket Support - Spring Cloud Function RSocket Support - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - 0.3.0 - - - - - org.springframework.boot - spring-boot-starter-rsocket - - - io.rsocket - rsocket-core - - - io.rsocket - rsocket-transport-netty - - - org.springframework.cloud - spring-cloud-function-context - - - io.rsocket.broker - rsocket-broker-client-spring - ${rsocket-broker.version} - true - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - io.rsocket.broker - rsocket-broker-spring - ${rsocket-broker.version} - test - - - - diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketMessageHandler.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketMessageHandler.java deleted file mode 100644 index a61e006f0..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketMessageHandler.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -import io.rsocket.frame.FrameType; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.core.MethodParameter; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.ByteArrayDecoder; -import org.springframework.core.codec.Decoder; -import org.springframework.core.codec.Encoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.handler.CompositeMessageCondition; -import org.springframework.messaging.handler.DestinationPatternsMessageCondition; -import org.springframework.messaging.handler.MessageCondition; -import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver; -import org.springframework.messaging.handler.invocation.reactive.HandlerMethodReturnValueHandler; -import org.springframework.messaging.handler.invocation.reactive.SyncHandlerMethodArgumentResolver; -import org.springframework.messaging.rsocket.DefaultMetadataExtractor; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.annotation.support.RSocketFrameTypeMessageCondition; -import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; -import org.springframework.messaging.rsocket.annotation.support.RSocketPayloadReturnValueHandler; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.CollectionUtils; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.RouteMatcher; -import org.springframework.util.RouteMatcher.Route; -import org.springframework.util.StringUtils; -import org.springframework.web.util.pattern.PathPatternRouteMatcher; - -/** - * An {@link RSocketMessageHandler} extension for Spring Cloud Function specifics. - * - * @author Artem Bilan - * @author Oleg Zhurakousky - * - * @since 3.1 - */ -class FunctionRSocketMessageHandler extends RSocketMessageHandler { - - public static final String RECONCILED_LOOKUP_DESTINATION_HEADER = "reconciledLookupDestination"; - - private final FunctionCatalog functionCatalog; - - private final FunctionProperties functionProperties; - - private final Field headersField; - - private final JsonMapper jsonMapper; - - private static final Method FUNCTION_APPLY_METHOD = - ReflectionUtils.findMethod(Function.class, "apply", (Class[]) null); - - private static final RSocketFrameTypeMessageCondition REQUEST_CONDITION = - new RSocketFrameTypeMessageCondition( - FrameType.REQUEST_FNF, - FrameType.REQUEST_RESPONSE, - FrameType.REQUEST_STREAM, - FrameType.REQUEST_CHANNEL); - - FunctionRSocketMessageHandler(FunctionCatalog functionCatalog, FunctionProperties functionProperties, JsonMapper jsonMapper) { - setHandlerPredicate((clazz) -> false); - this.functionCatalog = functionCatalog; - this.functionProperties = functionProperties; - this.headersField = ReflectionUtils.findField(MessageHeaders.class, "headers"); - this.headersField.setAccessible(true); - this.jsonMapper = jsonMapper; - } - - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public void afterPropertiesSet() { - List encoders = this.getEncoders(); - encoders.set(0, new MessageAwareJsonEncoder(this.jsonMapper)); - super.afterPropertiesSet(); - } - - @SuppressWarnings("unchecked") - @Override - public MetadataExtractor getMetadataExtractor() { - return new HeadersAwareMetadataExtractor((List>) this.getDecoders()); - } - - /** - * Will check if there is a function handler registered for destination before proceeding. - * This typically happens when user avoids using 'spring.cloud.function.definition' property. - */ - @Override - public Mono handleMessage(Message message) throws MessagingException { - if (!FrameType.SETUP.equals(message.getHeaders().get("rsocketFrameType"))) { - String destination = this.discoverAndInjectDestinationHeader(message); - - Set mappings = this.getDestinationLookup().keySet(); - if (!mappings.contains(destination)) { - FunctionInvocationWrapper function = FunctionRSocketUtils - .registerFunctionForDestination(destination, this.functionCatalog, this.getApplicationContext()); - this.registerFunctionHandler(new RSocketListenerFunction(function), destination); - } - } - - return super.handleMessage(message); - } - - @Override - protected RouteMatcher.Route getDestination(Message message) { - RouteMatcher.Route reconsiledDestination = (RouteMatcher.Route) message.getHeaders().get(RECONCILED_LOOKUP_DESTINATION_HEADER); - return reconsiledDestination == null ? super.getDestination(message) : reconsiledDestination; - } - - @Override - protected CompositeMessageCondition getMatchingMapping(CompositeMessageCondition mapping, Message message) { - List> result = new ArrayList<>(mapping.getMessageConditions().size()); - for (MessageCondition condition : mapping.getMessageConditions()) { - MessageCondition matchingCondition = condition instanceof DestinationPatternsMessageCondition - ? condition - : (MessageCondition) condition.getMatchingCondition(message); - if (matchingCondition == null) { - return null; - } - result.add(matchingCondition); - } - return new CompositeMessageCondition(result.toArray(new MessageCondition[0])); - } - - void registerFunctionHandler(Function function, String route) { - CompositeMessageCondition condition = - new CompositeMessageCondition(REQUEST_CONDITION, - new DestinationPatternsMessageCondition(new String[]{ route }, - obtainRouteMatcher())); - registerHandlerMethod(function, FUNCTION_APPLY_METHOD, condition); - } - - @Override - protected List initArgumentResolvers() { - List resolvers = super.initArgumentResolvers(); - return Collections.singletonList(new MessageHandlerMethodArgumentResolver(this.jsonMapper, resolvers)); - } - - @SuppressWarnings("unchecked") - @Override - protected List initReturnValueHandlers() { - return Collections.singletonList(new FunctionRSocketPayloadReturnValueHandler((List>) getEncoders(), - getReactiveAdapterRegistry())); - } - - private String discoverAndInjectDestinationHeader(Message message) { - - String destination; - if (!CollectionUtils.isEmpty(this.getApplicationContext().getBeansOfType(MessageRoutingCallback.class))) { - destination = RoutingFunction.FUNCTION_NAME; - } - else if (StringUtils.hasText(this.functionProperties.getRoutingExpression())) { - destination = RoutingFunction.FUNCTION_NAME; - this.updateMessageHeaders(message, destination); - } - else { - Route route = (Route) message.getHeaders().get(DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER); - destination = route.value(); - if (!StringUtils.hasText(destination)) { - destination = this.functionProperties.getDefinition(); - this.updateMessageHeaders(message, destination); - } - } - - if (!StringUtils.hasText(destination) && logger.isDebugEnabled()) { - logger.debug("Failed to discover function definition. Neither " - + "`spring.cloud.function.definition`, nor `.route()`, nor " - + "`spring.cloud.function.routing-expression` were provided. Will use empty string " - + "for lookup, which will work only if there is one function in Function Catalog"); - } - return destination; - } - - @SuppressWarnings("unchecked") - private void updateMessageHeaders(Message message, String destination) { - Map headersMap = (Map) ReflectionUtils - .getField(this.headersField, message.getHeaders()); - PathPatternRouteMatcher matcher = new PathPatternRouteMatcher(); - headersMap.put(RECONCILED_LOOKUP_DESTINATION_HEADER, matcher.parseRoute(destination)); - } - - protected static final class MessageHandlerMethodArgumentResolver implements SyncHandlerMethodArgumentResolver { - - private final Decoder decoder; - - private final JsonMapper jsonMapper; - - private final List resolvers; - - MessageHandlerMethodArgumentResolver(JsonMapper jsonMapper, List resolvers) { - this.decoder = new ByteArrayDecoder(); - this.jsonMapper = jsonMapper; - this.resolvers = resolvers; - } - - @Override - public boolean supportsParameter(MethodParameter parameter) { - return true; - } - - @SuppressWarnings("unchecked") - @Override - public Object resolveArgumentValue(MethodParameter parameter, - Message message) { - Object payload = message.getPayload(); - Flux data = payload instanceof DataBuffer - ? Flux.just((DataBuffer) payload) - : Flux.from((Publisher) payload); - - if (message.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE) - && MimeTypeUtils.APPLICATION_JSON_VALUE.equals(message.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString())) { - Flux argument = data.map(buffer -> { - byte[] bytePayload = this.decoder.decode(buffer, ResolvableType.forType(byte[].class), null, null); - if (JsonMapper.isJsonString(bytePayload)) { -// // could be array, map or string - Object structure = this.jsonMapper.fromJson(bytePayload, Object.class); - if (structure instanceof Map && ((Map) structure).containsKey(FunctionRSocketUtils.PAYLOAD)) { - return MessageBuilder.withPayload(((Map) structure).remove(FunctionRSocketUtils.PAYLOAD)) - .copyHeaders((Map) ((Map) structure).get(FunctionRSocketUtils.HEADERS)) - .build(); - } - } - return MessageBuilder.withPayload(bytePayload).copyHeadersIfAbsent(message.getHeaders()).build(); - }); - return MessageBuilder.createMessage(argument, message.getHeaders()); - } - else { // delegate to the existing argument resolvers - for (HandlerMethodArgumentResolver handlerMethodArgumentResolver : this.resolvers) { - if (handlerMethodArgumentResolver.supportsParameter(parameter)) { - Publisher arg = handlerMethodArgumentResolver.resolveArgument(parameter, message); - return MessageBuilder.withPayload(arg).copyHeadersIfAbsent(message.getHeaders()).build(); - } - } - return message; - } - } - } - - protected static final class FunctionRSocketPayloadReturnValueHandler extends RSocketPayloadReturnValueHandler { - - public FunctionRSocketPayloadReturnValueHandler(List> encoders, ReactiveAdapterRegistry registry) { - super(encoders, registry); - } - - @Override - public Mono handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, - Message message) { - - if (returnValue instanceof Publisher && !message.getHeaders().containsKey(RESPONSE_HEADER)) { - return Mono.from((Publisher) returnValue).then(); - } - return super.handleReturnValue(returnValue, returnType, message); - } - } - - /** - * This metadata extractor will ensure that any JSON data passed - * via metadata will be copied into Message headers. - */ - private static class HeadersAwareMetadataExtractor extends DefaultMetadataExtractor { - HeadersAwareMetadataExtractor(List> decoders) { - super(decoders); - super.metadataToExtract(MimeTypeUtils.APPLICATION_JSON, - new ParameterizedTypeReference>() { - }, (jsonMap, outputMap) -> outputMap.putAll(jsonMap) - ); - } - } - -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketUtils.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketUtils.java deleted file mode 100644 index a46e482f4..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/FunctionRSocketUtils.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import java.lang.reflect.Type; -import java.net.URI; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionRegistry; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.context.ApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.RSocketRequester.Builder; -import org.springframework.util.Assert; -import org.springframework.util.MimeTypeUtils; -import org.springframework.util.StringUtils; - -/** - * - * @author Oleg Zhurakousky - * - * @since 3.1 - * - */ -final class FunctionRSocketUtils { - - private static final Log LOGGER = LogFactory.getLog(FunctionRSocketUtils.class); - - public static String PAYLOAD = "payload"; - - public static String HEADERS = "headers"; - - - private static final Pattern WS_URI_PATTERN = Pattern.compile("^(https?|wss?)://.+"); - - private FunctionRSocketUtils() { - - } - - static FunctionInvocationWrapper registerFunctionForDestination(String functionDefinition, FunctionCatalog functionCatalog, - ApplicationContext applicationContext) { - - registerRSocketForwardingFunctionIfNecessary(functionDefinition, functionCatalog, applicationContext); - FunctionProperties functionProperties = applicationContext.getBean(FunctionProperties.class); - String acceptContentType = functionProperties.getExpectedContentType(); - if (!StringUtils.hasText(acceptContentType)) { - FunctionInvocationWrapper function = functionCatalog.lookup(functionDefinition); - Type outputType = function.getOutputType(); - acceptContentType = (outputType instanceof Class && String.class.isAssignableFrom((Class) outputType)) - ? MimeTypeUtils.TEXT_PLAIN_VALUE : MimeTypeUtils.APPLICATION_JSON_VALUE; - } - - FunctionInvocationWrapper function = functionCatalog.lookup(functionDefinition, acceptContentType); - function.setSkipOutputConversion(true); - return function; - } - - static void registerRSocketForwardingFunctionIfNecessary(String definition, FunctionCatalog functionCatalog, - ApplicationContext applicationContext) { - String[] names = StringUtils.delimitedListToStringArray(definition.replaceAll(",", "|").trim(), "|"); - for (String name : names) { - - if (functionCatalog.lookup(name) == null) { // this means RSocket - String[] functionToRSocketDefinition = StringUtils.delimitedListToStringArray(name, ">"); - if (functionToRSocketDefinition.length == 1) { - return; - } - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Registering RSocket forwarder for '" + name + "' function."); - } - - Assert.isTrue(functionToRSocketDefinition.length == 2, "Must only contain one output redirect. Was '" + name + "'."); - FunctionInvocationWrapper function = functionCatalog.lookup(functionToRSocketDefinition[0], MimeTypeUtils.APPLICATION_JSON_VALUE); - - String[] hostPort = StringUtils.delimitedListToStringArray(functionToRSocketDefinition[1], ":"); - - String forwardingUrl = functionToRSocketDefinition[1]; - Builder rsocketRequesterBuilder = applicationContext.getBean(Builder.class); - - RSocketRequester rsocketRequester = (WS_URI_PATTERN.matcher(forwardingUrl).matches()) - ? rsocketRequesterBuilder.websocket(URI.create(forwardingUrl)) - : rsocketRequesterBuilder.tcp(hostPort[0], Integer.parseInt(hostPort[1])); - - RSocketForwardingFunction rsocketFunction = - new RSocketForwardingFunction(function, rsocketRequester, null); - FunctionRegistration functionRegistration = - new FunctionRegistration<>(rsocketFunction, name); - functionRegistration.type( - FunctionTypeUtils.discoverFunctionTypeFromClass(RSocketForwardingFunction.class)); - ((FunctionRegistry) functionCatalog).register(functionRegistration); - } - } - } - - static Map sanitizeMessageToMap(Message message) { - Map messageMap = new HashMap<>(); - messageMap.put(PAYLOAD, message.getPayload()); - Map headers = new HashMap<>(); - for (String key : message.getHeaders().keySet()) { - if (key.equals("lookupDestination") || - key.equals("reconciledLookupDestination") || - key.equals(MessageHeaders.CONTENT_TYPE)) { - headers.put(key, message.getHeaders().get(key).toString()); - } - else if (!key.equals("rsocketRequester")) { - headers.put(key, message.getHeaders().get(key)); - } - } - messageMap.put(HEADERS, headers); - return messageMap; - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonDecoder.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonDecoder.java deleted file mode 100644 index 1398d3958..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonDecoder.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2021-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.rsocket; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.AbstractDecoder; -import org.springframework.core.codec.DecodingException; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.lang.Nullable; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -/** - * - * @author Oleg Zhurakousky - * @since 3.1 - * - */ -class MessageAwareJsonDecoder extends AbstractDecoder { - - private final JsonMapper jsonMapper; - - MessageAwareJsonDecoder(JsonMapper jsonMapper) { - super(MimeTypeUtils.APPLICATION_JSON); - this.jsonMapper = jsonMapper; - } - - @Override - public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) { - return mimeType != null && mimeType.isCompatibleWith(MimeTypeUtils.APPLICATION_JSON); - } - - @SuppressWarnings("unchecked") - @Override - public Object decode(DataBuffer dataBuffer, ResolvableType targetType, - @Nullable MimeType mimeType, @Nullable Map hints) - throws DecodingException { - - ResolvableType type = ResolvableType.forClassWithGenerics(Map.class, String.class, - Object.class); - Map messageMap = (Map) doDecode(dataBuffer, type, - mimeType, hints); - if (messageMap.containsKey(FunctionRSocketUtils.PAYLOAD)) { - Type requestedType = FunctionTypeUtils.getGenericType(targetType.getType()); - Object payload; - if (String.class.isAssignableFrom(FunctionTypeUtils.getRawType(targetType.getType()))) { - Object rawPayload = messageMap.get(FunctionRSocketUtils.PAYLOAD); - if (rawPayload instanceof byte[]) { - payload = new String((byte[]) rawPayload, StandardCharsets.UTF_8); - } - else { - payload = rawPayload; - } - } - else if (byte[].class.isAssignableFrom(FunctionTypeUtils.getRawType(targetType.getType()))) { - Object rawPayload = messageMap.get(FunctionRSocketUtils.PAYLOAD); - if (rawPayload instanceof String) { - payload = ((String) rawPayload).getBytes(StandardCharsets.UTF_8); - } - else { - payload = rawPayload; - } - } - else { - payload = this.jsonMapper.fromJson(messageMap.get(FunctionRSocketUtils.PAYLOAD), requestedType); - } -// if (String.class.isAssignableFrom(FunctionTypeUtils.getRawType(targetType.getType())) -// || byte[].class.isAssignableFrom(FunctionTypeUtils.getRawType(targetType.getType()))) { -// Object rawPayload = messageMap.get(FunctionRSocketUtils.PAYLOAD); -// if (rawPayload instanceof byte[]) { -// payload = new String((byte[]) rawPayload, StandardCharsets.UTF_8); -// } -// else { -// payload = rawPayload; -// } -// } -// else { -// payload = this.jsonMapper.fromJson(messageMap.get(FunctionRSocketUtils.PAYLOAD), requestedType); -// } - - if (FunctionTypeUtils.isMessage(targetType.getType())) { - return MessageBuilder.withPayload(payload).copyHeaders( - (Map) messageMap.get(FunctionRSocketUtils.HEADERS)) - .build(); - } - else { - return payload; - } - } - else { - return messageMap; - } - } - - private Object doDecode(DataBuffer dataBuffer, ResolvableType targetType, - @Nullable MimeType mimeType, @Nullable Map hints) - throws DecodingException { - - try { - byte[] data = toByteArray(dataBuffer.asInputStream()); - if (JsonMapper.isJsonStringRepresentsMap(data)) { - return this.jsonMapper.fromJson(data, targetType.getType()); - } - else { - Map messageMap = new HashMap<>(); - messageMap.put(FunctionRSocketUtils.PAYLOAD, data); - return messageMap; - } - } - catch (IOException ex) { - throw new IllegalStateException(ex); - } - finally { - DataBufferUtils.release(dataBuffer); - } - } - - private byte[] toByteArray(final InputStream input) throws IOException { - try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { - copyLarge(input, output, new byte[2048]); - return output.toByteArray(); - } - } - - private long copyLarge(final InputStream input, final OutputStream output, - final byte[] buffer) throws IOException { - long count = 0; - int n; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - @Override - public Flux decode(Publisher inputStream, - ResolvableType elementType, MimeType mimeType, Map hints) { - return Flux.from(inputStream).map(buffer -> decode(buffer, elementType, mimeType, hints)); - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonEncoder.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonEncoder.java deleted file mode 100644 index 02aa41045..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/MessageAwareJsonEncoder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2021-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.rsocket; - -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.AbstractEncoder; -import org.springframework.core.codec.ByteArrayEncoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - - - -/** - * @author Oleg Zhurakousky - * @since 3.1 - * - */ -/* - * We basically don't need it, but having it allows us not to depend on spring-web - */ -class MessageAwareJsonEncoder extends AbstractEncoder { - - private final JsonMapper mapper; - - private final boolean isClient; - - private final ByteArrayEncoder byteArrayEncoder; - - MessageAwareJsonEncoder(JsonMapper mapper) { - this(mapper, false); - } - - MessageAwareJsonEncoder(JsonMapper mapper, boolean isClient) { - super(MimeTypeUtils.APPLICATION_JSON); - this.mapper = mapper; - this.isClient = isClient; - this.byteArrayEncoder = new ByteArrayEncoder(); - } - - @Override - public boolean canEncode(ResolvableType elementType, MimeType mimeType) { - boolean canEncode = mimeType != null && mimeType.isCompatibleWith(MimeTypeUtils.APPLICATION_JSON); - if (canEncode && this.isClient) { - canEncode = (FunctionTypeUtils.isMessage(elementType.getType()) - || Map.class.isAssignableFrom(FunctionTypeUtils.getRawType(elementType.getType()))); - } - return canEncode; - } - - - @Override - public List getEncodableMimeTypes() { - return Collections.singletonList(MimeTypeUtils.APPLICATION_JSON); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, - ResolvableType valueType, @Nullable MimeType mimeType, @Nullable Map hints) { - - if (value instanceof Message) { - Object payload = ((Message) value).getPayload(); - value = FunctionRSocketUtils.sanitizeMessageToMap((Message) value); - if (payload instanceof byte[]) { - payload = new String((byte[]) payload, StandardCharsets.UTF_8); // safe for cases when we have JSON - ((Map) value).put(FunctionRSocketUtils.PAYLOAD, payload); - } - } - else if (!(value instanceof Map)) { - if (JsonMapper.isJsonString(value)) { - value = this.mapper.fromJson(value, valueType.getType()); - } - value = Collections.singletonMap(FunctionRSocketUtils.PAYLOAD, value); - } - byte[] data = this.mapper.toJson(value); - return this.byteArrayEncoder.encodeValue(data, bufferFactory, valueType, mimeType, hints); - } - - @Override - public Flux encode(Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - return Flux.from(inputStream).map(value -> - encodeValue(value, bufferFactory, elementType, mimeType, hints)); - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketAutoConfiguration.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketAutoConfiguration.java deleted file mode 100644 index e7cc2b28a..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketAutoConfiguration.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.rsocket.RSocketMessageHandlerCustomizer; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.messaging.rsocket.RSocketStrategies; - -/** - * Main configuration class for components required to support RSocket integration with - * spring-cloud-function. - * - * @author Oleg Zhurakousky - * @author Artem Bilan - * - * @since 3.1 - */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(FunctionProperties.class) -@ConditionalOnProperty(name = FunctionProperties.PREFIX + ".rsocket.enabled", matchIfMissing = true) -class RSocketAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - @Primary - FunctionRSocketMessageHandler functionRSocketMessageHandler(RSocketStrategies rSocketStrategies, - ObjectProvider customizers, FunctionCatalog functionCatalog, - FunctionProperties functionProperties, JsonMapper jsonMapper) { - - FunctionRSocketMessageHandler rsocketMessageHandler = new FunctionRSocketMessageHandler(functionCatalog, functionProperties, jsonMapper); - rsocketMessageHandler.setRSocketStrategies(rSocketStrategies); - customizers.orderedStream().forEach((customizer) -> customizer.customize(rsocketMessageHandler)); - return rsocketMessageHandler; - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketCustomizerConfiguration.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketCustomizerConfiguration.java deleted file mode 100644 index 82628e186..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketCustomizerConfiguration.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2021-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.rsocket; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.rsocket.messaging.RSocketStrategiesCustomizer; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.rsocket.RSocketStrategies.Builder; - -/** - * @author Oleg Zhurakousky - * - * @since 3.2 - */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties({ FunctionProperties.class, RSocketFunctionProperties.class }) -public class RSocketCustomizerConfiguration { - - @Bean - RSocketStrategiesCustomizer rSocketStrategiesCustomizer(JsonMapper jsonMapper) { - return new RSocketStrategiesCustomizer() { - @Override - public void customize(Builder strategies) { - strategies - .encoders(encoders -> { - encoders.add(0, new MessageAwareJsonEncoder(jsonMapper, true)); - }) - .decoders(decoders -> { - decoders.add(0, new MessageAwareJsonDecoder(jsonMapper)); - }); - } - }; - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketForwardingFunction.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketForwardingFunction.java deleted file mode 100644 index 8da7e76e4..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketForwardingFunction.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.messaging.Message; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.support.GenericMessage; - - -/** - * Wrapper over an instance of target Function (represented by {@link FunctionInvocationWrapper}) - * which will use the result of the invocation of such function as an input to another RSocket - * effectively composing two functions over RSocket. - *

- * Note: the remote RSocket route is not required to represent Spring Cloud Function binding. - * - * @author Oleg Zhurakousky - * @author Artem Bilan - * - * @since 3.1 - * - */ -class RSocketForwardingFunction implements Function, Publisher>> { - - private static final Log LOGGER = LogFactory.getLog(RSocketForwardingFunction.class); - - private final FunctionInvocationWrapper targetFunction; - - private final RSocketRequester rSocketRequester; - - RSocketForwardingFunction(FunctionInvocationWrapper targetFunction, RSocketRequester rsocketRequester, - String remoteFunctionName) { - - this.targetFunction = targetFunction; - this.rSocketRequester = rsocketRequester; - } - - @Override - public Publisher> apply(Message input) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Executing: " + this.targetFunction); - } - - Mono targetFunctionCall = Mono.just(input) - .map(this.targetFunction) - .cast(Message.class) - .map(Message::getPayload); - - return this.rSocketRequester - .route("") - .data(targetFunctionCall, byte[].class) - .retrieveFlux(byte[].class) - .map(GenericMessage::new); - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketFunctionProperties.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketFunctionProperties.java deleted file mode 100644 index f6c137ccc..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketFunctionProperties.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.function.context.FunctionProperties; - -/** - * Main configuration properties for RSocket integration with spring-cloud-function. - * The prefix for these properties is `spring.cloud.function.rscocket`. - * - * @author Oleg Zhurakousky - * @author Spencer Gibb - * @since 3.1 - */ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX + ".rsocket") -public class RSocketFunctionProperties { - - private boolean enabled; - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketListenerFunction.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketListenerFunction.java deleted file mode 100644 index 53f81e688..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketListenerFunction.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import java.util.Map; -import java.util.function.Function; - -import io.rsocket.frame.FrameType; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -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.MessageHeaders; -import org.springframework.messaging.rsocket.annotation.support.RSocketFrameTypeMessageCondition; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.util.MimeTypeUtils; - -/** - * A function wrapper which is bound onto an RSocket route. - * - * @author Oleg Zhurakousky - * @author Artem Bilan - * - * @since 3.1 - */ -class RSocketListenerFunction implements Function> { - - private final FunctionInvocationWrapper targetFunction; - - RSocketListenerFunction(FunctionInvocationWrapper targetFunction) { - Assert.isTrue(targetFunction != null, "Failed to discover target function. \n" - + "To fix it you should either provide 'spring.cloud.function.definition' property " - + "or if you are using RSocketRequester provide valid function definition via 'route' " - + "operator (e.g., requester.route(\"echo\"))"); - this.targetFunction = targetFunction; - } - - - @SuppressWarnings("unchecked") - @Override - public Publisher apply(Object input) { - /* - * We need to maintain the input typeless to ensure that no encoder/decoders will attempt any conversion. - * That said it will always be Message> - */ - Message> inputMessage = (Message>) input; - - FrameType frameType = RSocketFrameTypeMessageCondition.getFrameType(inputMessage); - switch (frameType) { - case REQUEST_FNF: - return handle(inputMessage); - case REQUEST_RESPONSE: - case REQUEST_STREAM: - case REQUEST_CHANNEL: - return handleAndReply(inputMessage); - default: - throw new UnsupportedOperationException(); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Mono handle(Message> messageToProcess) { - if (this.targetFunction.isRoutingFunction()) { - Flux dataFlux = Flux.from(messageToProcess.getPayload()) - .map(payload -> MessageBuilder.createMessage(payload, messageToProcess.getHeaders())); - return dataFlux.doOnNext(this.targetFunction).then(); - } - else if (this.targetFunction.isConsumer()) { - Flux dataFlux = Flux.from(messageToProcess.getPayload()) - .map(payload -> this.buildReceivedMessage(payload, messageToProcess.getHeaders())); - - dataFlux = FunctionTypeUtils.isPublisher(this.targetFunction.getInputType()) - ? dataFlux.transform((Function) this.targetFunction) - : dataFlux.doOnNext(this.targetFunction); - - return dataFlux.then(); - } - else { - return Mono.error(new IllegalStateException("Only 'Consumer' can handle 'fire-and-forget' RSocket frame.")); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Flux handleAndReply(Message> messageToProcess) { - Flux dataFlux = Flux.from(messageToProcess.getPayload()) - .map(payload -> this.buildReceivedMessage(payload, messageToProcess.getHeaders())); - - if (this.targetFunction.getInputType() != null && FunctionTypeUtils.isPublisher(this.targetFunction.getInputType())) { - dataFlux = dataFlux.transform((Function) this.targetFunction); - } - else { - dataFlux = dataFlux.flatMap((data) -> { - Map messageMap = FunctionRSocketUtils.sanitizeMessageToMap((Message) data); - Message sanitizedMessage = MessageBuilder.withPayload(messageMap.remove(FunctionRSocketUtils.PAYLOAD)) - .copyHeaders((Map) messageMap.get(FunctionRSocketUtils.HEADERS)) - .build(); - Object result = this.targetFunction.isSupplier() ? this.targetFunction.apply(null) : this.targetFunction.apply(sanitizedMessage); - - Publisher resultPublisher = result instanceof Publisher - ? (Publisher) result - : Mono.just(result); - return Flux.from(resultPublisher).map(v -> extractPayloadIfNecessary(v)); - }); - } - return dataFlux; - } - - private Message buildReceivedMessage(Object mayBeMessage, MessageHeaders messageHeaders) { - return mayBeMessage instanceof Message - ? MessageBuilder.fromMessage((Message) mayBeMessage).copyHeadersIfAbsent(messageHeaders).build() - : MessageBuilder.withPayload(mayBeMessage).copyHeadersIfAbsent(messageHeaders).build(); - } - - /* - * This will ensure that unless CT is application/json for which we provide Message aware encoder/decoder - * the payload is extracted since no other available encoders/decoders understand Message. - */ - private Object extractPayloadIfNecessary(Object output) { - if (output instanceof Message) { - Message resultMessage = (Message) output; - Object contentType = resultMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE); - if (contentType != null && contentType.toString().equals(MimeTypeUtils.APPLICATION_JSON_VALUE)) { - return output; - } - else { - return resultMessage.getPayload(); - } - } - return output; - } -} diff --git a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketRoutingAutoConfiguration.java b/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketRoutingAutoConfiguration.java deleted file mode 100644 index abf37dbd2..000000000 --- a/spring-cloud-function-rsocket/src/main/java/org/springframework/cloud/function/rsocket/RSocketRoutingAutoConfiguration.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import io.rsocket.broker.client.spring.BrokerClientAutoConfiguration; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.rsocket.RSocketConnectorConfigurer; - -/** - * Configuration for components required to support RSocket Routing Client - * integration with spring-cloud-function. - * - * @author Spencer Gibb - * @since 3.1 - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass(BrokerClientAutoConfiguration.class) -@ConditionalOnProperty(name = FunctionProperties.PREFIX + ".rsocket.enabled", matchIfMissing = true) -@AutoConfigureBefore(BrokerClientAutoConfiguration.class) -@AutoConfigureAfter(RSocketAutoConfiguration.class) -class RSocketRoutingAutoConfiguration { - - @Bean - RSocketConnectorConfigurer functionRSocketConnectorConfigurer( - FunctionRSocketMessageHandler handler) { - return connector -> connector.acceptor(handler.responder()); - } - -} diff --git a/spring-cloud-function-rsocket/src/main/resources/META-INF/spring.factories b/spring-cloud-function-rsocket/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-rsocket/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-rsocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-rsocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index fdb2838db..000000000 --- a/spring-cloud-function-rsocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.cloud.function.rsocket.RSocketAutoConfiguration -org.springframework.cloud.function.rsocket.RSocketCustomizerConfiguration diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessageRoutingCallbackRSocketTests.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessageRoutingCallbackRSocketTests.java deleted file mode 100644 index 349566c1e..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessageRoutingCallbackRSocketTests.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2021-2022 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.rsocket; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeTypeUtils; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - */ -public class MessageRoutingCallbackRSocketTests { - - @Test - public void testRoutingWithRoutingCallback() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(RoutingCallbackFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.expected-content-type=text/plain", - "--spring.rsocket.server.port=0"); - ) { - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - int port = applicationContext.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - - // imperative - rsocketRequesterBuilder.tcp("localhost", port) - .route("foo") - .metadata("{\"func_name\":\"uppercase\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - - // imperative Message - rsocketRequesterBuilder.tcp("localhost", port) - .route("foo") - .metadata("{\"func_name\":\"uppercaseMessage\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - - // reactive - rsocketRequesterBuilder.tcp("localhost", port) - .route("foo") - .metadata("{\"func_name\":\"uppercaseReactive\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - - // reactive - rsocketRequesterBuilder.tcp("localhost", port) - .route("foo") - .metadata("{\"func_name\":\"uppercaseReactiveMessage\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @EnableAutoConfiguration - @Configuration - public static class RoutingCallbackFunctionConfiguration { - @Bean - public MessageRoutingCallback customRouter() { - return new MessageRoutingCallback() { - @Override - public String routingResult(Message message) { - return (String) message.getHeaders().get("func_name"); - } - }; - } - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function, Message> uppercaseMessage() { - return m -> MessageBuilder.withPayload(m.getPayload().toUpperCase()).copyHeaders(m.getHeaders()).build(); - } - - @Bean - public Function, Flux> uppercaseReactive() { - return flux -> flux.map(v -> v.toUpperCase()); - } - - @Bean - public Function>, Flux>> uppercaseReactiveMessage() { - return flux -> flux.map(m -> MessageBuilder.withPayload(m.getPayload().toUpperCase()).copyHeaders(m.getHeaders()).build()); - } - - @Bean - public Function concat() { - return v -> v + v; - } - } -} diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessagingTests.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessagingTests.java deleted file mode 100644 index 5238a87ba..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/MessagingTests.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright 2021-2022 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.rsocket; - -import java.util.Map; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.messaging.Message; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - */ -public class MessagingTests { - - @Test - public void testPojoToStringViaMessage() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoToString") - .data(message) - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("RICKY") - .expectComplete() - .verify(); - } - } - - @SuppressWarnings("rawtypes") - @Test - public void testPojoToStringViaMessageMap() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - JsonMapper jsonMapper = applicationContext.getBean(JsonMapper.class); - Map map = jsonMapper.fromJson(message, Map.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoToString") - .data(map) - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("RICKY") - .expectComplete() - .verify(); - } - } - - @Test - public void testPojoToStringViaMessageExpectMessage() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - Message result = rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoToString") - .data(message) - .retrieveMono(new ParameterizedTypeReference>() { - }) - .block(); - - assertThat(result.getPayload()).isEqualTo("RICKY"); - assertThat(result.getHeaders().get("someHeader")).isEqualTo("foo"); - } - } - - @Test - public void testPojoMessageToPojoViaMessage() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - Person result = new Person(); - result.setName(p.getName().toUpperCase()); - rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(message) - .retrieveMono(Person.class) - .as(StepVerifier::create) - .expectNext(result) - .expectComplete() - .verify(); - } - } - - @SuppressWarnings("rawtypes") - @Test - public void testPojoMessageToPojoViaMap() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - JsonMapper jsonMapper = applicationContext.getBean(JsonMapper.class); - Map map = jsonMapper.fromJson(message, Map.class); - - Person result = new Person(); - result.setName(p.getName().toUpperCase()); - rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(map) - .retrieveMono(Person.class) - .as(StepVerifier::create) - .expectNext(result) - .expectComplete() - .verify(); - } - } - - @Test - public void testPojoMessageToPojoViaMessageExpectMessage() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setName("Ricky"); - Message message = MessageBuilder.withPayload(p).setHeader("someHeader", "foo").build(); - - Message result = rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(message) - .retrieveMono(new ParameterizedTypeReference>() { - }) - .block(); - - assertThat(result.getPayload().getName()).isEqualTo("RICKY"); - assertThat(result.getHeaders().get("someHeader")).isEqualTo("foo"); - } - } - - @Test - public void testPojoMessageToPojoViaMessageExpectMessageRawPayload() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Message message = MessageBuilder.withPayload("{\"name\":\"bob\"}".getBytes()) - .setHeader("someHeader", "foo") - .build(); - - Message result = rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(message) - .retrieveMono(new ParameterizedTypeReference>() { - }) - .block(); - - assertThat(result.getPayload()).isEqualTo("{\"name\":\"BOB\"}".getBytes()); - assertThat(result.getHeaders().get("someHeader")).isEqualTo("foo"); - } - } - - @Test - public void testPojoMessageToPojoViaMessageExpectMessageStringPayload() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Message message = MessageBuilder.withPayload("{\"name\":\"bob\"}") - .setHeader("someHeader", "foo") - .build(); - - Message result = rsocketRequesterBuilder.tcp("localhost", port) - .route("pojoMessageToPojo") - .data(message) - .retrieveMono(new ParameterizedTypeReference>() { - }) - .block(); - - assertThat(result.getPayload()).isEqualTo("{\"name\":\"BOB\"}"); - assertThat(result.getHeaders().get("someHeader")).isEqualTo("foo"); - } - } - - @Test - public void testPojoToMessageMap() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(MessagingConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - Person p = new Person(); - p.setName("Ricky"); - - Message> result = rsocketRequesterBuilder.tcp("localhost", port) - .route("echoMessageMap") - .data(p) - .retrieveMono(new ParameterizedTypeReference>>() { - }) - .block(); - - assertThat(((Map) result.getPayload()).get("name")).isEqualTo("Ricky"); - } - } - - private int getLocalRsocketPort(ConfigurableApplicationContext context) { - return context.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - } - - @EnableAutoConfiguration - @Configuration - public static class MessagingConfiguration { - - @Bean - public Function pojoToString() { - return v -> { - return v.getName().toUpperCase(); - }; - } - - @Bean - public Function>, Message>> echoMessageMap() { - return v -> { - assertThat(v.getHeaders()).containsKey("rsocketFrameType"); - assertThat(v.getHeaders()).containsKey("lookupDestination"); - return v; - }; - } - - @Bean - public Function>>, Flux>>> echoMessageMapReactive() { - return v -> { - return v; - }; - } - - @Bean - public Function, Person> pojoMessageToPojo() { - return p -> { - assertThat(p.getHeaders().get("someHeader").equals("foo")); - Person newPerson = new Person(); - newPerson.setName(p.getPayload().getName().toUpperCase()); - return newPerson; - }; - } - - @Bean - public Function, Message> pojoMessageToPojoMessage() { - return p -> { - assertThat(p.getHeaders().get("someHeader").equals("foo")); - Person newPerson = new Person(); - newPerson.setName(p.getPayload().getName().toUpperCase()); - return MessageBuilder.withPayload(newPerson).copyHeaders(p.getHeaders()).setHeader("xyz", "hello").build(); - }; - } - - } - - public static class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof Person && (this.name.equals(((Person) obj).name)); - } - } -} diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationRoutingTests.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationRoutingTests.java deleted file mode 100644 index 9fb7a4a1e..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationRoutingTests.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2021-2022 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.rsocket; - - -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.core.publisher.Sinks; -import reactor.test.StepVerifier; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.DestinationPatternsMessageCondition; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 3.1 - */ -public class RSocketAutoConfigurationRoutingTests { - @Test - public void testRoutingWithRoute() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.routing-expression=headers.func_name", - "--spring.cloud.function.expected-content-type=text/plain", - "--spring.rsocket.server.port=0"); - ) { - int port = applicationContext.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("") - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - rsocketRequesterBuilder.tcp("localhost", port) - .route(RoutingFunction.FUNCTION_NAME) - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - } - } - - @Test - public void testRoutingWithDefinition() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase", - "--spring.cloud.function.routing-expression=headers.func_name", - "--spring.cloud.function.expected-content-type=text/plain", - "--spring.rsocket.server.port=0"); - ) { - int port = applicationContext.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("") - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - rsocketRequesterBuilder.tcp("localhost", port) - .route(RoutingFunction.FUNCTION_NAME) - .metadata("{\"func_name\":\"echo\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - - } - } - - @Test - public void testRoutingWithDefinitionMessageFunction() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase", - "--spring.cloud.function.routing-expression=headers.func_name", - "--spring.cloud.function.expected-content-type=text/plain", - "--spring.rsocket.server.port=0"); - ) { - int port = applicationContext.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .metadata("{\"func_name\":\"uppercaseMessage\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - - } - } - - @EnableAutoConfiguration - @Configuration - public static class SampleFunctionConfiguration { - - final Sinks.One consumerData = Sinks.one(); - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function, String> uppercaseMessage() { - return msg -> { - assertThat(msg.getHeaders() - .get(DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER)).toString().equals("uppercase"); - assertThat(msg.getHeaders() - .get(FunctionRSocketMessageHandler.RECONCILED_LOOKUP_DESTINATION_HEADER)).toString().equals(RoutingFunction.FUNCTION_NAME); - return msg.getPayload().toUpperCase(); - }; - } - - @Bean - public Function concat() { - return v -> v + v; - } - - @Bean - public Function echo() { - return v -> v; - } - - @Bean - public Function, Flux> uppercaseReactive() { - return flux -> flux.map(v -> { - System.out.println("Uppercasing: " + v); - return v.toUpperCase(); - }); - } - - @Bean - public Consumer log() { - return this.consumerData::tryEmitValue; - } - - @Bean - public Supplier source() { - return () -> "test data"; - } - - - } - -} diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java deleted file mode 100644 index f0b942174..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RSocketAutoConfigurationTests.java +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright 2020-2022 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.rsocket; - -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Sinks; -import reactor.test.StepVerifier; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.rsocket.context.RSocketServerBootstrap; -import org.springframework.boot.rsocket.server.RSocketServer; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 3.1 - */ -public class RSocketAutoConfigurationTests { - - @Test - public void testNonExistingFunctionInRoute() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("foo") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectError() - .verify(); - } - } - - @Test - public void testNonExistingFunctionInRouteSingleFunctionInCatalog() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SingleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("blah") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("hello") - .expectComplete() - .verify(); - } - } - - - - @Test - public void testImperativeFunctionAsRequestReplyWithDefinition() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @SuppressWarnings("unchecked") - @Test - public void testWithCborContentType() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - Person p = new Person(); - p.setAge(23); - p.setName("Bob"); - Map m = rsocketRequesterBuilder - .dataMimeType(MimeType.valueOf("application/cbor")) - .tcp("localhost", port) - .route("echoMap") - .data(p) - .retrieveMono(Map.class).block(); - assertThat(m.get("name")).isEqualTo("Bob"); - assertThat(m.get("age")).isEqualTo(23); - } - } - - @Test - @Disabled - public void testImperativeFunctionAsRequestReplyWithDefinitionExplicitExpectedOutputCt() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase", - "--spring.cloud.function.expected-content-type=application/json", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("\"HELLO\"") - .expectComplete() - .verify(); - } - } - - @Test - public void testImperativeFunctionAsRequestReply() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testWithRouteAndDefinition() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=echo", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testImperativeFunctionAsRequestReplyWithComposition() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase|concat") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLOHELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testSupplierAsRequestReply() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("source") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("test data") - .expectComplete() - .verify(); - } - } - - @Test - public void testImperativeFunctionAsRequestStream() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .data("\"hello\"") - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testImperativeFunctionAsRequestChannel() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - //.data(Flux.just("\"Ricky\"", "\"Julien\"", "\"Bubbles\"")) - .data(Flux.just("Ricky", "Julien", "Bubbles")) - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("RICKY", "JULIEN", "BUBBLES") - .expectComplete() - .verify(); - } - } - - @Test - public void testReactiveFunctionAsRequestReply() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercaseReactive") - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testReactiveFunctionAsRequestStream() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercaseReactive") - .data("hello") - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercaseReactive") - .data("hello") - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercaseReactive") - .data("hello") - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("HELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testReactiveFunctionAsRequestChannel() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercaseReactive") - .data(Flux.just("\"Ricky\"", "\"Julien\"", "\"Bubbles\"")) - .retrieveFlux(String.class) - .as(StepVerifier::create) - .expectNext("RICKY", "JULIEN", "BUBBLES") - .expectComplete() - .verify(); - } - } - - @Test - public void testRequestReplyFunctionWithDistributedComposition() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase|concat", - "--spring.rsocket.server.port=0"); - ) { - int portA = getLocalRsocketPort(applicationContext); - - try ( - ConfigurableApplicationContext applicationContext2 = - new SpringApplicationBuilder(AdditionalFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=reverse>localhost:" + portA + "|wrap", - "--spring.rsocket.server.port=0"); - ) { - - int portB = getLocalRsocketPort(applicationContext2); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext2.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", portB) - .route("reverse>localhost:" + portA + "|wrap") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("(OLLEHOLLEH)") - .expectComplete() - .verify(); - } - } - } - - @Disabled("TODO") - @Test - public void testCompositionOverWebSocket() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.REACTIVE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=uppercase|concat", - "--spring.rsocket.server.transport=websocket", - "--spring.rsocket.server.mapping-path=rsockets", - "--server.port=0"); - ) { - ConfigurableEnvironment environment = applicationContext.getEnvironment(); - String httpServerPort = environment.getProperty("local.server.port"); - - try ( - ConfigurableApplicationContext applicationContext2 = - new SpringApplicationBuilder(AdditionalFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.definition=reverse>http://localhost:" + httpServerPort + "/rsockets/uppercase|wrap", - "--spring.rsocket.server.port=0"); - ) { - RSocketServerBootstrap serverBootstrap = applicationContext2.getBean(RSocketServerBootstrap.class); - RSocketServer server = (RSocketServer) ReflectionTestUtils.getField(serverBootstrap, "server"); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext2.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", server.address().getPort()) - .route("reverse") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("\"(OLLEHOLLEH)\"") - .expectComplete() - .verify(); - } - } - } - - @Test - public void testFireAndForgetConsumer() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - - SampleFunctionConfiguration config = applicationContext.getBean(SampleFunctionConfiguration.class); - - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route("log") - .data("\"hello\"") - .send() - .as(StepVerifier::create) - .expectComplete() - .verify(); - String result = config.consumerData.asMono().block(); - assertThat(result).isEqualTo("hello"); - } - } - - @Test - public void testRsocketRoutesForAllFunctions() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(AdditionalFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - RSocketServerBootstrap serverBootstrap = applicationContext.getBean(RSocketServerBootstrap.class); - RSocketServer server = (RSocketServer) ReflectionTestUtils.getField(serverBootstrap, "server"); - - RSocketRequester requester = rsocketRequesterBuilder.tcp("localhost", server.address().getPort()); - - requester.route("reverse") - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("olleh") - .expectComplete() - .verify(); - - requester.route("wrap") - .data("\"hello\"") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("(hello)") - .expectComplete() - .verify(); - } - } - - @Test - public void testRoutingWithRoutingFunction() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.cloud.function.routing-expression=headers.function_definition", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - rsocketRequesterBuilder.tcp("localhost", port) - .route(RoutingFunction.FUNCTION_NAME) - .metadata("{\"function_definition\":\"uppercase|concat\"}", MimeTypeUtils.APPLICATION_JSON) - .data("hello") - .retrieveMono(String.class) - .as(StepVerifier::create) - .expectNext("HELLOHELLO") - .expectComplete() - .verify(); - } - } - - @Test - public void testByteArrayInOut() { - try ( - ConfigurableApplicationContext applicationContext = - new SpringApplicationBuilder(SampleFunctionConfiguration.class) - .web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--spring.rsocket.server.port=0"); - ) { - int port = getLocalRsocketPort(applicationContext); - - RSocketRequester.Builder rsocketRequesterBuilder = - applicationContext.getBean(RSocketRequester.Builder.class); - - String result = rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .data("hello".getBytes()) - .retrieveMono(String.class) - .block(); - - assertThat(result).isEqualTo("HELLO"); - - byte[] resultBytes = rsocketRequesterBuilder.tcp("localhost", port) - .route("uppercase") - .data("hello".getBytes()) - .retrieveMono(byte[].class) - .block(); - - assertThat(resultBytes).isEqualTo("HELLO".getBytes()); - } - } - - private int getLocalRsocketPort(ConfigurableApplicationContext context) { - return context.getEnvironment().getProperty("local.rsocket.server.port", Integer.class); - } - - @EnableAutoConfiguration - @Configuration - public static class SampleFunctionConfiguration { - - final Sinks.One consumerData = Sinks.one(); - - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - - @Bean - public Function concat() { - return v -> v + v; - } - - - @Bean - public Function echo() { - return v -> v; - } - - @Bean - public Function, Map> echoMap() { - return v -> v; - } - - @Bean - public Function, Flux> uppercaseReactive() { - return flux -> flux.map(v -> { - System.out.println("Uppercasing: " + v); - return v.toUpperCase(); - }); - } - - @Bean - public Consumer log() { - return this.consumerData::tryEmitValue; - } - - @Bean - public Supplier source() { - return () -> "test data"; - } - - } - - @EnableAutoConfiguration - @Configuration - public static class AdditionalFunctionConfiguration { - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - @Bean - public Function wrap() { - return v -> "(" + v + ")"; - } - - } - - @EnableAutoConfiguration - @Configuration - public static class SingleFunctionConfiguration { - @Bean - public Function echo() { - return v -> v; - } - } - - public static class Person { - private String name; - private int age; - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public int getAge() { - return age; - } - public void setAge(int age) { - this.age = age; - } - } - -} diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RoutingBrokerTests.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RoutingBrokerTests.java deleted file mode 100644 index e44919ee4..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/RoutingBrokerTests.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2020-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.rsocket; - -import java.time.Duration; -import java.util.function.Function; - -import io.rsocket.broker.client.spring.BrokerMetadata; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.rsocket.RSocketRequester; - -/** - * @author Spencer Gibb - * @author Oleg Zhurakousky - * @since 3.1 - */ -@Disabled -public class RoutingBrokerTests { - - ConfigurableApplicationContext functionContext; - ConfigurableApplicationContext brokerContext; - ConfigurableApplicationContext clientContext; - - @AfterEach - public void cleanup() { - if (functionContext != null) { - functionContext.close(); - } - if (brokerContext != null) { - brokerContext.close(); - } - if (clientContext != null) { - clientContext.close(); - } - } - - @Test - public void testRoutingWithProperty() throws Exception { - this.setup(true); - RSocketRequester requester = clientContext.getBean(RSocketRequester.class); - // route(uppercase) used to find function, must match io.rsocket.broker.client.address entry - Mono result = requester.route("uppercase") - // auto creates metadata - .data("\"hello\"") - .retrieveMono(String.class); - - StepVerifier - .create(result) - .expectNext("HELLO") - .expectComplete() - .verify(Duration.ofSeconds(15)); - } - - @Test - public void testRoutingWithMessage() throws Exception { - this.setup(false); - RSocketRequester requester = clientContext.getBean(RSocketRequester.class); - BrokerMetadata metadata = clientContext.getBean(BrokerMetadata.class); - Mono result = requester.route("uppercase") // used to find function - .metadata(metadata.address("samplefn")) - .data("\"hello\"") - .retrieveMono(String.class); - - StepVerifier - .create(result) - .expectNext("HELLO") - .expectComplete() - .verify(Duration.ofSeconds(15)); - } - - private void setup(boolean routingWithProperty) { - int brokerProxyPort = TestSocketUtils.findAvailableTcpPort(); - int brokerClusterPort = TestSocketUtils.findAvailableTcpPort(); - // start broker - brokerContext = new SpringApplicationBuilder(SimpleConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.io.rsocket.broker=TRACE", - "--spring.cloud.function.rsocket.enabled=false", - "--io.rsocket.broker.client.enabled=false", - "--io.rsocket.broker.enabled=true", - "--io.rsocket.broker.uri=tcp://localhost:" + brokerProxyPort, - "--io.rsocket.broker.cluster.uri=tcp://localhost:" + brokerClusterPort); - - // start function connecting to broker, service-name=samplefn - functionContext = new SpringApplicationBuilder(SampleFunctionConfiguration.class).web(WebApplicationType.NONE) - .run("--logging.level.org.springframework.cloud.function=DEBUG", - "--logging.level.io.rsocket.broker.client=TRACE", - "--io.rsocket.broker.client.enabled=true", - "--io.rsocket.broker.client.service-name=samplefn", - "--io.rsocket.broker.client.brokers[0]=tcp://localhost:" + brokerProxyPort, - "--io.rsocket.broker.enabled=false", - "--spring.cloud.function.definition=uppercase"); - - // start testclient connecting to broker, for RSocketRequester - clientContext = new SpringApplicationBuilder(SimpleConfiguration.class).web(WebApplicationType.NONE).run( - "--logging.level.io.rsocket.broker.client=TRACE", - "--spring.cloud.function.rsocket.enabled=false", - "--io.rsocket.broker.client.enabled=true", - "--io.rsocket.broker.client.service-name=testclient", - routingWithProperty ? "--io.rsocket.broker.client.address.uppercase.service_name=samplefn" : "", - "--io.rsocket.broker.client.brokers[0]=tcp://localhost:" + brokerProxyPort, - "--io.rsocket.broker.enabled=false"); - } - - - @EnableAutoConfiguration - @Configuration - public static class SimpleConfiguration { - - } - - @EnableAutoConfiguration - @Configuration - public static class SampleFunctionConfiguration { - @Bean - public Function uppercase() { - return v -> v.toUpperCase(); - } - } -} diff --git a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/TestSocketUtils.java b/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/TestSocketUtils.java deleted file mode 100644 index 27722015e..000000000 --- a/spring-cloud-function-rsocket/src/test/java/org/springframework/cloud/function/rsocket/TestSocketUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2022-2022 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.rsocket; - -import java.net.InetAddress; -import java.net.ServerSocket; -import java.util.Random; - -import javax.net.ServerSocketFactory; - -/** - * Simple test utility to find a random available TCP port. - *

Inspired by the now removed {@code org.springframework.util.SocketUtils} and is only used in a testing capacity. - * - * @author Chris Bono - * @deprecated will soon be removed or consolidated - do not use further - */ -@Deprecated -public final class TestSocketUtils { - - private static final Random random = new Random(System.nanoTime()); - - private TestSocketUtils() { - } - - /** - * Find an available TCP port randomly selected from the range {@code 1024-65535}. - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort() { - int minPort = 1024; - int maxPort = 65535; - int portRange = maxPort - minPort; - int candidatePort; - int searchCounter = 0; - do { - if (searchCounter > portRange) { - throw new IllegalStateException(String.format( - "Could not find an available TCP port after %d attempts", searchCounter)); - } - candidatePort = minPort + random.nextInt(portRange + 1); - searchCounter++; - } - while (!isPortAvailable(candidatePort)); - - return candidatePort; - } - - private static boolean isPortAvailable(int port) { - try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( - port, 1, InetAddress.getByName("localhost")); - serverSocket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } -} diff --git a/spring-cloud-function-rsocket/src/test/resources/application.properties b/spring-cloud-function-rsocket/src/test/resources/application.properties deleted file mode 100644 index 83911652b..000000000 --- a/spring-cloud-function-rsocket/src/test/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -io.rsocket.broker.enabled=false -io.rsocket.broker.client.enabled=false diff --git a/spring-cloud-function-samples/function-functional-sample-aws/.jdk8 b/spring-cloud-function-samples/function-functional-sample-aws/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-functional-sample-aws/build.gradle b/spring-cloud-function-samples/function-functional-sample-aws/build.gradle deleted file mode 100644 index a641c315f..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/build.gradle +++ /dev/null @@ -1,93 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.2.0.BUILD-SNAPSHOT' - wrapperVersion = '1.0.17.RELEASE' - shadowVersion = '5.1.0' - } - repositories { - mavenLocal() - jcenter() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } - } - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:${shadowVersion}" - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - classpath("io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'org.springframework.boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' -apply plugin: 'io.spring.dependency-management' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "3.0.0.BUILD-SNAPSHOT" - awsLambdaEventsVersion = "2.0.2" - awsLambdaCoreVersion = "1.1.0" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -assemble.dependsOn = [shadowJar, thinJar] - -jar { - manifest { - attributes 'Main-Class': 'example.Config' - } -} - -import com.github.jengelman.gradle.plugins.shadow.transformers.* - -shadowJar { - classifier = 'aws' - dependencies { - exclude( - dependency("org.springframework.cloud:spring-cloud-function-web:${springCloudFunctionVersion}")) - } - // Required for Spring - mergeServiceFiles() - append 'META-INF/spring.handlers' - append 'META-INF/spring.schemas' - append 'META-INF/spring.tooling' - transform(PropertiesFileTransformer) { - paths = ['META-INF/spring.factories'] - mergeStrategy = "append" - } -} - -configurations { - testCompile.extendsFrom(compileOnly) -} - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile("org.springframework.cloud:spring-cloud-function-adapter-aws") - compile("org.springframework.cloud:spring-cloud-starter-function-webflux") - compile("org.springframework.boot:spring-boot-configuration-processor") - compileOnly("com.amazonaws:aws-lambda-java-events:${awsLambdaEventsVersion}") - compileOnly("com.amazonaws:aws-lambda-java-core:${awsLambdaCoreVersion}") - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-functional-sample-aws/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-functional-sample-aws/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-functional-sample-aws/gradlew.bat b/spring-cloud-function-samples/function-functional-sample-aws/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-functional-sample-aws/pom.xml b/spring-cloud-function-samples/function-functional-sample-aws/pom.xml deleted file mode 100644 index 4187df05e..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/pom.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-functional-sample-aws - 0.0.1-SNAPSHOT - jar - - function-functional-sample-aws - Spring Cloud Function Sample for AWS Lambda functional style - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 1.0.27.RELEASE - 3.9.0 - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - com.amazonaws - aws-lambda-java-events - ${aws-lambda-events.version} - - - com.amazonaws - aws-lambda-java-core - 1.1.0 - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - false - true - aws - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - 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 deleted file mode 100644 index a237eff87..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/FunctionConfiguration.java +++ /dev/null @@ -1,37 +0,0 @@ -package example; - -import java.util.function.Function; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.support.GenericApplicationContext; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; - -@SpringBootConfiguration -public class FunctionConfiguration implements ApplicationContextInitializer { - - /* - * You need this main method (empty) or explicit example.FunctionConfiguration - * in the POM to ensure boot plug-in makes the correct entry - */ - public static void main(String[] args) { - // empty unless using Custom runtime at which point it should include - // FunctionalSpringApplication.run(FunctionConfiguration.class, args); - } - - @Override - public void initialize(GenericApplicationContext context) { - Function function = (str) -> str + str.toUpperCase(); - - context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(function).type(FunctionTypeUtils.functionType(String.class, String.class))); - - context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(new TestFunction()).type(FunctionTypeUtils.functionType(APIGatewayProxyRequestEvent.class, APIGatewayProxyResponseEvent.class))); - - } -} diff --git a/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/TestFunction.java b/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/TestFunction.java deleted file mode 100644 index b097d0ad5..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/main/java/example/TestFunction.java +++ /dev/null @@ -1,13 +0,0 @@ -package example; - -import java.util.function.Function; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; - -public class TestFunction implements Function { - @Override - public APIGatewayProxyResponseEvent apply(APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent) { - return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("ok"); - } -} diff --git a/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/application.properties b/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/application.properties deleted file mode 100644 index af6da4bf5..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -logging.level.org.springframework.cloud=DEBUG diff --git a/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/log4j.properties b/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/log4j.properties deleted file mode 100644 index f644d953c..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/main/resources/log4j.properties +++ /dev/null @@ -1,20 +0,0 @@ -log4j.rootCategory=DEBUG, LAMBDA -PID=???? -LOG_LEVEL_PATTERN=%5p -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender -log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout -log4j.appender.LAMBDA.layout.conversionPattern=${LOG_PATTERN} -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.apache.sshd.common.util.SecurityUtils -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.crsh.ssh=WARN -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN -log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN -log4j.category.org.thymeleaf=WARN diff --git a/spring-cloud-function-samples/function-functional-sample-aws/src/test/java/example/MapTests.java b/spring-cloud-function-samples/function-functional-sample-aws/src/test/java/example/MapTests.java deleted file mode 100644 index 289a8c9ff..000000000 --- a/spring-cloud-function-samples/function-functional-sample-aws/src/test/java/example/MapTests.java +++ /dev/null @@ -1,31 +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 example; - -import org.junit.jupiter.api.Test; - -/** - * @author Dave Syer - * - */ -public class MapTests { - - @Test - public void test() { - - } -} diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/README.adoc b/spring-cloud-function-samples/function-sample-aws-custom-bean/README.adoc deleted file mode 100644 index fc1fd761f..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/README.adoc +++ /dev/null @@ -1,12 +0,0 @@ -This sample uses the custom runtime type on AWS lambda using @Bean style configuration. -However, changing configuration to functional bean registration is supported as well and shown in `function-sample-aws-custom` example. - -To run the app in AWS choose the "Custom Runtime" runtime type, and upload the -.zip file that gets built on the command line with `mvn package` (look -in `target`). -There are several functions defined in the `com.example.LambdaApplication`, so identify the selected function in "Handler" -You can also use function composition (e.g., `uppercase|reverse`) - -You can test any function in this example with any String as input, but the Lambda UI only allows valid JSON as -test data, so you will have to escape the input with double quotes. - 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 deleted file mode 100644 index 6a54471cd..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/pom.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - io.spring.sample - function-sample-aws-custom-bean - 0.0.1-SNAPSHOT - AWS Custom Runtime - @Bean sample - Demo project for Spring Cloud Function with custom AWS Lambda runtime using @Bean style - - - 1.0.27.RELEASE - 4.1.0-SNAPSHOT - - - - - - com.amazonaws - aws-lambda-java-events - 3.9.0 - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - org.slf4j - slf4j-jdk14 - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - maven-surefire-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-assembly-plugin - - - zip - package - - single - - false - - - - - src/assembly/zip.xml - - - - - - - - - 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-bean/src/assembly/zip.xml b/spring-cloud-function-samples/function-sample-aws-custom-bean/src/assembly/zip.xml deleted file mode 100644 index 62e8b951e..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/assembly/zip.xml +++ /dev/null @@ -1,35 +0,0 @@ - - zip - - zip - - - - - target/classes - / - true - - bootstrap - - - - target/classes - / - true - 0775 - - bootstrap - - - - - - /lib - false - runtime - - - \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/java/com/example/LambdaApplication.java b/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/java/com/example/LambdaApplication.java deleted file mode 100644 index 7fb2ecec8..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/java/com/example/LambdaApplication.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.example; - -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.util.ObjectUtils; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; - -@SpringBootApplication -public class LambdaApplication { - - private static Log logger = LogFactory.getLog(LambdaApplication.class); - - @Bean - public Consumer consume() { - return value -> { - logger.info("Consuming: " + value); - }; - } - - @Bean - public Function uppercase() { - return value -> { - logger.info("UPPERCASING: " + value); - return value.toUpperCase(); - }; - } - - @Bean - public Function extractPayloadFromGatewayEvent() { - return value -> { - logger.info("ECHO Payload from Gateway Event: " + value.getBody()); - return value.getBody(); - }; - } - - @Bean - public Function, Message> echoMessage() { - return value -> { - logger.info("ECHO MESSAGE: " + value); - return value; - }; - } - - @Bean - public Function reverse() { - return value -> { - logger.info("REVERSING: " + value); - return new StringBuilder(value).reverse().toString(); - }; - } - - - - public static void main(String[] args) { - logger.info("==> Starting: LambdaApplication"); - if (!ObjectUtils.isEmpty(args)) { - logger.info("==> args: " + Arrays.asList(args)); - } - SpringApplication.run(LambdaApplication.class, args); - } - -} diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/application.properties deleted file mode 100644 index dbb9aec79..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.main.web-application-type=none -logging.level.org.springframework.cloud=DEBUG \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/bootstrap b/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/bootstrap deleted file mode 100755 index ab39ddb01..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/main/resources/bootstrap +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -java -Dspring.main.web-application-type=none -Dspring.jmx.enabled=false \ - -noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \ - -Djava.security.egd=file:/dev/./urandom \ - -cp .:`echo lib/*.jar | tr ' ' :` com.example.LambdaApplication diff --git a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/test/resources/testBootstrap b/spring-cloud-function-samples/function-sample-aws-custom-bean/src/test/resources/testBootstrap deleted file mode 100755 index 142d4caad..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom-bean/src/test/resources/testBootstrap +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -while true -do - sleep 1 -done \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-custom/README.adoc b/spring-cloud-function-samples/function-sample-aws-custom/README.adoc deleted file mode 100644 index a0948a6ed..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/README.adoc +++ /dev/null @@ -1,11 +0,0 @@ -This sample uses the custom runtime type on AWS lambda using function bean registration style configuration. -However, changing configuration to @Bean registration is supported as well and shown in `function-sample-aws-custom-bean` example. - -To run the app in AWS choose the "Custom Runtime" runtime type, and upload the -.zip file that gets built on the command line with `mvn package` (look -in `target`). -There is a single function defined in the `com.example.LambdaApplication` - `uppercase` which you would typically -identified as "Handler", but since it's the only one any value would do, so keeping default "hello.handler" is fine. - -You can test it with any String as input, but the Lambda UI only allows valid JSON as -test data, so you will have to escape the input with double quotes. diff --git a/spring-cloud-function-samples/function-sample-aws-custom/pom.xml b/spring-cloud-function-samples/function-sample-aws-custom/pom.xml deleted file mode 100644 index 4bde5f60b..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/pom.xml +++ /dev/null @@ -1,192 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - io.spring.sample - function-sample-aws-custom - 0.0.1-SNAPSHOT - function-sample-aws-custom - Demo project for Spring Cloud Function with custom AWS Lambda runtime - - - 1.0.27.RELEASE - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - org.springframework.cloud - spring-cloud-function-web - test - - - org.springframework.boot - spring-boot-starter-web - - - jakarta.servlet - jakarta.servlet-api - provided - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - - maven-surefire-plugin - - - com/example/ContainerTests.java - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-assembly-plugin - - - zip - package - - single - - false - - - - - src/assembly/zip.xml - - - - - - - - - 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 - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release-local - - false - - - - diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/assembly/zip.xml b/spring-cloud-function-samples/function-sample-aws-custom/src/assembly/zip.xml deleted file mode 100644 index 62e8b951e..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/assembly/zip.xml +++ /dev/null @@ -1,35 +0,0 @@ - - zip - - zip - - - - - target/classes - / - true - - bootstrap - - - - target/classes - / - true - 0775 - - bootstrap - - - - - - /lib - false - runtime - - - \ No newline at end of file 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 deleted file mode 100644 index da9d85523..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/main/java/com/example/LambdaApplication.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.example; - -import java.util.function.Function; - -import org.apache.commons.logging.Log; -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.FunctionalSpringApplication; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.support.GenericApplicationContext; - -@SpringBootApplication -public class LambdaApplication - implements ApplicationContextInitializer { - - private static Log logger = LogFactory.getLog(LambdaApplication.class); - - public Function uppercase() { - return value -> { - logger.info("Processing: " + value); - if (value.equals("error")) { - throw new IllegalArgumentException("Intentional"); - } - return value.toUpperCase(); - }; - } - - public static void main(String[] args) { - FunctionalSpringApplication.run(LambdaApplication.class, args); - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()).type(FunctionTypeUtils.functionType(String.class, String.class))); - } -} diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/application.properties deleted file mode 100644 index 48d1c32ec..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -#spring.cloud.function.web.export.enabled=true -#spring.cloud.function.web.export.debug=true -spring.main.web-application-type=none -logging.level.org.springframework.cloud=DEBUG \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/bootstrap b/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/bootstrap deleted file mode 100755 index ab39ddb01..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/main/resources/bootstrap +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -java -Dspring.main.web-application-type=none -Dspring.jmx.enabled=false \ - -noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \ - -Djava.security.egd=file:/dev/./urandom \ - -cp .:`echo lib/*.jar | tr ' ' :` com.example.LambdaApplication diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/test/java/com/example/LambdaApplicationTests.java b/spring-cloud-function-samples/function-sample-aws-custom/src/test/java/com/example/LambdaApplicationTests.java deleted file mode 100644 index b7e560f00..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/test/java/com/example/LambdaApplicationTests.java +++ /dev/null @@ -1,45 +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 com.example; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.cloud.function.adapter.test.aws.AWSCustomRuntime; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; - - -/** - * @author Oleg Zhurakousky - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"spring.main.web-application-type=servlet"}) -@ContextConfiguration(classes = {AWSCustomRuntime.class}, initializers = LambdaApplication.class) -@TestPropertySource(properties = {"_HANDLER=uppercase"}) -public class LambdaApplicationTests { - @Autowired - private AWSCustomRuntime aws; - - @Test - void testWithCustomRuntime() throws Exception { - assertThat(aws.exchange("\"oleg\"").getPayload()).isEqualTo("\"OLEG\""); - assertThat(aws.exchange("\"dave\"").getPayload()).isEqualTo("\"DAVE\""); - } -} diff --git a/spring-cloud-function-samples/function-sample-aws-custom/src/test/resources/testBootstrap b/spring-cloud-function-samples/function-sample-aws-custom/src/test/resources/testBootstrap deleted file mode 100755 index 142d4caad..000000000 --- a/spring-cloud-function-samples/function-sample-aws-custom/src/test/resources/testBootstrap +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -while true -do - sleep 1 -done \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-native/.gitignore b/spring-cloud-function-samples/function-sample-aws-native/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f17644411d6e840bd5a10c6ecda0175f18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` zq{Nq+*dAH{EQyjZw_d4E!54gka%phEHEm}XI5o%$)&Z+*4qj<_EChj#X+kA1t|O3V@_RzoBA(&rgxwAF+zhjMY6+Xi>tw<6k+vgz=?DPJS^! zei4z1%+2HDqt}Ow+|2v^3IZQkTR<&IRxc0IZ_-Di>CErQ+oFQ~G{;lJSzvh9rKkAiSGHlAB$1}ZRdR^v zs2OS)Pca>Ap(RaSs7lM2GfJ#%F`}$!)K4#RaGJ_tY}6PMzY{5uHi}HjU>Qb~wlXQ) zdd(`#gdDgN_cat+Q#1q&iH{`26k}U3UR5(?FXM>Jm{W%IKpM4Jo{`3aEHN)XI&Bwx zs}a_P|M)fwG1Tybl)Rkw#D__n_uM+eDn*}}uN4z)3dq)U)n>pIk&pbWpPt@TXlB?b z8AAgq!2_g-!QL>xdU4~4f6CB06j6@M?60$f;#gpb)X1N0YO*%fw2W`m=M@%ZGWPx; z)r*>C$WLCDX)-_~S%jEx%dBpzU6HNHNQ%gLO~*egm7li)zfi|oMBt1pwzMA$x@ zu{Ht#H}ZBZwaf0Ylus3KCZ*qfyfbTUYGuOQI9>??gLrBPf-0XB84}sCqt5Q(O$M& zoJ+1hx4Wp#z?uex+Q1crm2ai?kci;AE!yriBr}c@tQdCnhs$P-CE8jdP&uriF`WFt>D9wO9fCS0WzaqUKjV_uRWg>^hIC!n-~q=1K87NAECZb^W?R zjbI&9pJ)4SSxiq06Zasv*@ATm7ghLgGw3coL-dn6@_D-UhvwPXC3tLC)q3xA2`^D{ z&=G&aeSCN)6{2W6l@cg&2`cCja~D2N{_>ZQ)(5oSf!ns1i9szOif~I8@;2b)f2yQ5 zCqr{lGy5(^+d!<0g??wFzH^wuv=~0)g55&^7m8Ptk3y$OU|eI7 zIovLvNCoY%N(aW#=_C%GDqEO|hH3O9&iCp+LU=&CJ(=JYDGI;&ag&NKq}d;B`TonC zK+-t8V5KjcmDyMR@jvDs|7lkga4>TQej$5B+>A`@{zE&?j-QbQWk4J*eP2@%RzQ{J z?h`1~zwArwi^D7k9~%xtyf(2&$=GsP*n-fTKneej-y6y(3nNfC7|0{drDx{zz~cSs z<_+d2#ZDst@+`w{mwzmn?dM2aB;E;bS-Opq$%w@WnDwa$hUGL90u9c=as)+_6aO10 zLR|CR8nr<2DQTvkaH0QDsyn@TYCs7Nk3lN}Ix$)JM0*zf=0Ad$w9j723W#%{r8V&`{wx-8kSv#)mZ{FU%UZDIi zvbgLHyJ>z0BZe`GNM$Q;D6D48#zc9s(4^SGr>u-arE}okN62N{zuwX)@FL5>$ib=b z5Wtm~!ojD3X|g59lw%^hE?dL;c^bgVtBOkJxQR{Eb*nR1wVM&fJQ{<))bn9e3bSlu z3E-qpLbAE(S^I4mVn`?lycoV!yO!Qj_4qYgsg7tXR)Gu2%1)5FZu&lY7x>bU`eE}x zSZ5c`z~^&$9V?eEH!^Rp-Fz3WiCvEgf`Tq}CnWRZY+@jZ{2NewmyGUM6|xa3Sh7)v zj6d&NWUVqu9f-&W)tQ>Y%Ea!e76@y!Vm*aQp|wU5u<%knNvHZ!U}`fp*_)mIWba=j z*w9~{f5pD;zCmEWePjM#ERNiNjv!SnM-&rGpB9Nmiv}J+hwB&0f_+x?%*lgJFRHsqfFDPwyvh8<*xLT0u_BeEHw{q+UGj=$4udEx)Vq#sV zKB3+_C!RUKy?ac3-`+}dL2!D_2(5=8&@hBf`-AbU`-<_3>Ilqkg6qSI>9G(@Kx?g<0h0K&31$AR>R%d}{%DyXPss$&c^ja7NR z$0AN7Fl$>VpGxqHW15CjxAa6DUVmCpQNbOwBv8D^Y{bXg28> zEQE9xl?CWh0gS6%Y=G4Cy($Vb>jBb2f_dm#0_B<_Ce`|~Obt_Xp^nkR zK%o_`{h1XkWn}i|5Dp#q8D(;k;2|+{DAG{2gJgPNQ=KZ=FKY@d>QEu6W;oLsE(1}< zpnwSEj(K{Bu^#CXdi7L_$!X`QOx^tA1c{&-XTHo3G?3(H*&VM~*Aud?8%FU=dE&kV zJ$SqZoj^g@(q9x;7B30J$(-qUml{?3e+I^Cf?X0PpLr}m zS}W9`QaCwINRU&D5>j9O*j6S}R1`7{5+{d-xUlI~)U!^4+*b5tkuon-Msz03Z{{Kp zH!GAXoyr#1K;t5o#h#a%Lzj3XQGqM0TRnfu$(fsQe^wb_?W!m!+7r55q>svWN`k~T zS(gk9bi|@+8wg;dR<&0f;MpwQbY27$N{{laPQk3@3uCz$w1&jq)`uW*yn!Pe-V^%Q zR9)cW;UB~ODlwolWFAX?ik#_|v)AtHNwoq72E9Jg#v2e5SErf+7nTleI8&}%tn6hf zuz#5YtRs94Ui&E_1PakHfo+^t-{#ewhO*j5ls-zhm^C{kCARNEB1aORsxE!1SXBRz z6Oc-^#|0W6=7AJ;I|}pH#qby@i^C+Vsu9?zdtkE{0`oO_Hw|N=Lz9Is8j}R zI+8thGK?(KSZ5ZW4nQG1`v(=0Jd*0gIlavVihzo#fPaa=}(Rqdxl3^6O8K+{MqU`;1iTJ$<^k)Nms(A$j?A-wHJKvh9 zUHW3}JkE;x?FETPV8DFTxFLY8eSAd%C8vp?P_EuaMakmyFN_e?Hf|LBctnncUb}zF zIGP4WqtKCydoov~Bi<_I%y%$l+})!;SQVcP?>)9wM3q-GE6t9*LfoePBlo{gx~~e{g_XM5PQ8Y5dsuG%3Xq}I&qcY6 zTCo?<6E%)O$A2torq3-g8j3?GGd){+VHg@gM6Kw|E($M9}3HVIyL1D9321C zu#6~~h<<*=V7*ria%j^d5A;S^E;n!mOnFppfi+4)!BQ@#O2<|WH$RS~)&2Qol|@ff zFR#zmU(|jaqCXPA@q?UhrgbMO7zNXQYA@8$E+;4Bz7g=&zV-)=&08J_noLAz#ngz$ zA)8L8MrbXIDZuFsR_M(DsdX)s$}yH!*bLr{s$YWl5J?alLci=I#p`&MbL4`5bC}=2 z^8-(u4v2hs9*us}hjB!uiiY6vvv&QWJcVLTJ=SFG=lpR+S4Cd91l}oZ+B-*ehY2Ic_85)SRSa% zMEL~a3xrvH8ZnMIC!{9@pfOT7lrhxMf^8N20{CJXg}M35=`50S;6g-JYwjwj!K{^) z5Bohf6_G6z=+0V8&>F8xLbJ4mkCVu^g66#h&?tL z9odv&iW21IAh~y9D-DupKP-NcernF2(*RsFkAsM<$<>@-Cl1?&XAi4+Mh2Zm@2x#u zWH&J^1=8G|`|H2%94bnjUZyI>QACu9FS}^$lbtzzCz4AMspqGYEwFFM<%G!Oc$+;7 z3r_L!H~PR}5n8+3-&4v*fFr$uK{y_VamM0*TKn^))nQsn5U?7Iv?`4|Oy&m6himAG z%=a;2ji3f_RtDPqkwR>ISxhnS0f)E`ITo}TR!zIxPwECZy#jzo%q{BNYtd!<IP_S+=*yDOk1GgwLqe!d9esV@3$iVAm1!8RoE| zqnTz;5a)B(~~KcP)c>?+ysFAlAGF4EBor6)K{K*Kn>B(&QtMAkR^ynG%k%UbJpKM zI$}qQXXP3PISHe_vTFssbcL`irhG2zN7J((3ZFmh*bnPuiK~=#YG=820hXqOON#HI<0bvIT{z&SaqRvqaMG-d5<06zdP?-kIH{%UMR$Xn@S}Hx3 zFjg}6no}vN_512D+RIn-mo9^_Li-)WI5%VigYt{Jd!RyI%d|-LqJU$y3aJ*a$y6$1 zjyTuIF2&t>1rPlw&k5OVLhrYBvk5Vl8T(*Gd?Alqi}> z<@-`X_o@9EOB8Ik&?|;lvKHFU@#O+?T!kEf&oJUaLzN;>!}!!e1WIs(T}V#Irf$AK z42`x`z-9ogxd@%CS;D5S z2M^b;Pu)q)c&_KBO!va-4xnI57L7V@*_I_r4vU)z>xk5z6PDVqg92R7_iZH|VlO_B z#8R`5HZVn?ou>czd>gZ~s;w4ZkzVXJNP8FiezlB5JXe6Z-OLsDw%N7!(135!Vl2Lb zLYI79?U{h#W-_#W6hf`<$BQHJCu5ehv?IF+-uxUqt~j!ZW1cxfiEJal^q7~RMWQ0a z2CEaPa1_p|P6qRmmeKgas*N}@(2tH%U37-<5i(DSnVOFFxg-Sv%7&{hPeRh{U`&ufGz=V|JdYQ2sG5 zk%3JimSwQFP=Yr?u_beSG^B$nnh$4hrxb4lpTTiUFRQEZ3ulr+L3m;>;Io?D;jG6Wjj!b)nsZds<6 zX@cD%+aVr!ra~F7HYr`TB!|y-t)HSb^FQt zbo+_XP44IWJGGxg73JyhBjKMSv`77ngDOw}6Eve6ZIol$Q5s65d(1-sP{BU{1_y)7 zF8sh5A~jxRHk=wq3c5i3*e&otCd9>cstT?IQ&D4slC-&^q!ut1;WAQ}fE}Y+jU}r{ zmpSI%sW?})RAm8}$WUU+V$PmQOF5gSKOGQ2;LF-E(gd<67rYu2K| zom8mOppa%XJ6C(@I7-*opqLn73e9BMFStaBER?suJ{jte1$vA%z?$_`Em=a=(?T-q z*A=VZOQ`P{co!*UUKyV@Rd-c#*wmb7v<%rN=TGFmWmqhbj#&+?X|3bZYAjbNGTv~O zs7SIYi3VgW6@?=PGnbNNZIWaY^*+ChW&a)A$uqH8xxehwx2`<1w6mag?zuHbsVJiO$a)tQ zuBBoR>rLfhpA@)Qf`8BwRMx886%9HP5rOR%YCy9pQ|^Xw!=Mcnwx8j=(ZE)P-tJ&s zON&Nsr%14jS@K+IvrJj720NkCR*C(j&aI$EFCV)w$9M<#LdihyRKdzTjJPI|t9_S} z--#oF#;F?Y1KN%_yE);Bxv}9PWZphz_g5mReOKR`y%9UZ=n}GXWw?E$T1%NAfK1Ad z|0$Lp^;sntA>}=ybW)mkxNv1?hkZ`<8hCemcT5 zYl6$I^bhXDzPlz<>6zOy3Fu*3?>#q$;1fJ>nuxyx#&<&x6Y}j zCU&VmtCJ`;aYN+qP}nwr%s2ZQC|Z**axS^?iGu+x^{{>FIv!k0#HaXtEG=*C7kPe!mMnknbn}TKpp6Xv9 zVvq&%A3nmY^N*XTg&+=wO>(|{uTwm;ZP9@+M)6%T zwXPh-&{+aAfv^ZCzOEb;yj>A=f5Pbu)7T{9PT3u>#w*%?K8jqEF%I>A?q;E%CXn)f z|0ohNa5DMv@HVk^vT(L=HBtH*Vzo81L?)M=g7)>@j*vUx?S zxqZo23n3vn@K-Q@bx3lLT+5=fB_oz8+p?P;@*UU<-u)jb5WFEXzoc+8*EC5P6(HWr zY$mfFr=L&G>(jvl8US2fLQqTzHtAGizfR*;W4-kN2^I>L3KkXgx=e*}+i*N($}{?c zi=Q67G)oEMW{|Gdsm{)|V)5Evo}KLj%}gIe>98FFoNTLrJX z-ACRdewnT1w#Egct%wpGg~q%?!$}>$_UJPC4SP0^)G_$d4jN0jBEx}+rcd*^aDtnx zewG{`m!oSbQ?A~FZ6L{&V0hUE+b$DxjO_;oskFha>@gzy(jDnzGO>z3Tzz|i&Dakg zFid5$;SFxINis^4JzK5XIVabKoP`=ZWp|p|t{hTi8n|#XE=-rINwJ*blo?=%Se(qw zkW7x5Qs(LV5RVGxu2e&4);c73lY#0(iZo1x=MY;7mW`uUQIY+$_PqH`4a`6O#urwU zE6(FrvyExmB{c5z*YAj_P&t??F1t6TN2N!$N#~02u(t(PDVyD)$mL3hqKQ4E91N#GOIngPr&pUb-f_Z4*XV8`p1pq+mzrUlUY=4~i|3RDo;Lo36U}uwm zaOah}mO8c@%J*~~{Up7_7->8|3x<}WemgaMA}h>xD17Fey@V9;LgjQFSBS(A<+2kCP9( zlkD%;oXzWtZ_hgu0IxeTjH`6=vi|t_04Btl32=g8swD1oZguWr4|lx0RuXoDHbh27 z+ks?gkVWYnr~_{h+PzQjQ(#8kaJai4We{F!JuqCzU0t*+H{n6i3;K<>_6XUn1n)}) zJ?}JCUPYhT9S1Hi-M+$(Z**%fz7Z%IiMN6%kD>wh%r4#C?Ge4{>w9o??Vbehy9!3@ zffZs8?LGxyWQr@yB(|%~Aa>fVj3$O=i{K*f;?h-a@-ce{(cY8qByOCA1r0;NC}}gr zcC^fCa$Ot`42n>`ehclOAqBo7L&D6Mi=;M5!pd@jj$H z?U7LQWX_u7bHpBzF7L-s4*`C)`dUrbEIgKy5=QHsi7%#&WYozvQOXrNcG{~HIIM%x zV^eEHrB=(%$-FXVCvH@A@|nvmh`|agsu9s1UhmdPdKflZa7m&1G`3*tdUI5$9Z>*F zYy|l8`o!QqR9?pP4D7|Lqz&~*Rl-kIL8%z?mi`BQh9Pk9a$Z}_#nRe4NIwqEYR(W0 z1lAKVtT#ZTXK2pwfcCP%Apfo#EVU|strP=o4bbt3j zP?k0Bn$A&Xv$GTun3!izxU#IXsK1GQt;F0k`Tglr{z>v2>gCINX!vfs`aqag!S*AG5Z`y-# zUv_u&J4r;|EA`r!-gsoYGn<^nSZLH-nj1SRGc0MRG%LWVL)PckFn9z!ebIJ}eg+ix zIJo7GN;j1s$D6!({bYW)auypcB~eAWN;vhF%(l=|RR})$TOn;ldq^@8ZPi<%Xz~{Z zQQ|KAJ@JHaX!Ka2nhP%Cb^I}V6_C|e1SjOQpcPMMwfNz#U@Az|+rmH*Zn=cYJu-KR z{>f++Z~P=jm)4-7^yc#52U4qeNcBRYb!hhT3Q7Ngu5t@CvY*ygxu^Eh?2l6= zhdqN{QEaP(!p>1p1*toD!TllHH6EH~S%l9`mG62dyAd+?}1(vf@N*x^6vhEFU<-RqS7#12*q-xtU z5d|F^n%WSAQHnm-vL)4L-VvoUVvO0kvhpIg57Wf@9p;lYS5YfrG9jtrr?E<_JL{q% z7uPQ52{)aP{7<_v^&=J)?_|}Ep*`{dH-=cDt*65^%LodzPSH@+Z~;7sAL}ZECxQv+;z*f;(?k)>-Lp@jBh9%J`XotGJO(HcJc!21iZ98g zS-O!L9vpE(xMx1mf9DIcy8J5)hGpT!o|C8H4)o-_$BR!bDb^zNiWIT6UA{5}dYySM zHQT8>e*04zk1)?F99$dp5F^2Htt*jJ=( zH(#XwfEZ`EErdI~k(THhgbwNK9a(()+Ha1EBDWVRLSB?0Q;=5Y(M0?PRJ>2M#uzuD zmf5hDxfxr%P1;dy0k|ogO(?oahcJqGgVJmb=m16RKxNU3!xpt19>sEsWYvwP{J!u& zhdu+RFZ4v8PVYnwc{fM7MuBs+CsdV}`PdHl)2nn0;J!OA&)^P23|uK)87pmdZ@8~F$W)lLA}u#meb zcl7EI?ng$CAA;AN+8y~9?aon#I*BgYxWleUO+W3YsQxAUF@2;Lu-m#U?F(tFRNIYA zvXuKXpMuxLjHEn&4;#P|=^k+?^~TbcB2pzqPMEz1N%;UDcf{z2lSiwvJs(KhoK+3^2 zfrmK%Z-ShDHo^OUl@cfy#(cE=fZvfHxbQ!Chs#(vIsL%hf55_zyx>0|h2JT=|7JWo z+Uth3y@G;48O|plybV_jER4KV{y{$yL5wc#-5H&w(6~)&1NfQe9WP99*Kc+Z^!6u7 zj`vK@fV-8(sZW=(Si)_WUKp0uKT$p8mKTgi$@k}(Ng z#xPo-5i8eZl6VB8Bk%2=&`o=v+G7g|dW47~gh}b3hDtjW%w)47v#X!VYM}Z7hG1GI zj16;ufr@1^yZ*w3R&6pB8PMbuz%kQ%r=|F4+a!Gw2RBX6RD5c!3fU@+QCq#X7W@Q5 zuVQ}Uu0dzN+2mSX5)KV%CsU;2FL%B6YT`10$8JR^#;jOO1x?t()Q_gI zxpQr2HI0_^@ge0hNt&MQAI`yJ1Zhd-fpR{rdNmRkEEDu7SpB)QOP4ajV;UBZZZK<6 zWds;!f+|}iP-kqWAH#1@QisJpjcg`+s80!LhAG@(eMad|zcln~oE8}9l5!K{^zf~( zd=HArZ5+Mryc$uNa`@|GSdOX=y}8GZc-%p8W@OM)uk2DfmhQXCU1E#y3XJ>|+XdW2 z)FQLeK38}u_D(5E{GV|YT^rI4qds2{-r<@@@@SG@u&4LbC z5o|KKqVM{?wk$5>2?t*I?IHdh~gljn_2m2zqZNJEEz4Mb$o&I3_UAg#$B{0u$uF4-q}{ zzs5+k@qOe08!CGLGmy3eRrcuqsgB*B>i8c3>3=T^Hv>nL{{u)jtNc6tLbL7KxfUr; z=Pp14Nz+ggjuwd~*oRJ)xWwGwdge+~b!E%c3Gzw6`vT>CCxE0t6v5Z`tw1oKCcm68A~Dbc zgbhP6bkWwSQ=#5EsX*O9Sm^}EwmQQzt2V2phrqqe2y)w8;|&t6W?lUSOTjeU%PKXC z3Kw$|>1YrfgUf6^)h(|d9SRFO_0&Cvpk<+i83DLS_}jgt~^YFwg0XWQSKW?cnBUVU}$R9F3Uo;N#%+js-gOY@`B4+9DH zYuN|s&@2{9&>eH?p1WVQcdDx&V(%-kz&oSSnvqzcXC3VsggWet1#~bRj5lBJDo#zF zSz))FHQd8>3iSw{63m`Pgy_jkkj9LTmJ&!J(V0E~&}HJ4@nXp<(miz$sb;(I<8s!7 zZyezu!-+X81r03486gAlx@n#aKx_93DREBtNcYln*8oliQ zbh0~SkAgHXX%C6}HwN(TRwaK2k_$Y}PxKId;jYt=S1Bf<8s@(IL?k3u1(f^V%TYO1 zA_jPf*V)SLEZFWS#y>M&p$LoSk+%ubs`)H%WEZf=F)RKh&x;i)uLIGJ94~A4m$(;S z;1rQC{m>--`WHFcaFA&5#7~vz|5S;{fB(7pPnG;@$D~C0pZYNEG?B8X*GB2e4{Qk; za1oop8OvHqs1Lk6B`AuYOv4`y`IgM315iTr{VUVc9WeOG;xE z%eDQgE4rb_B%vuT>N?^K zRvPnQwG%7RjO26+DY!OXWjgBu4^!)W-+ob_G&nX++))pD->QdRCo0spZN?Y*J#@-q z)fk-fJvZYz8)GSxYc^oXYIM;Pw}ftHW+a3dis#dXx^OS^m-~FlwcVr6MXv78fNI!i z51K-2t&!&IZ4(GF=mT@;qIp!&R(I@UiWPPz)%Us&(FdAAGxZ-+6^UZ7em`J-F#_3r zLkHym@VAnZFM$J~?0b@&O`l4YXyvOQ+OqalbZ0{g{qD{neY_xno1ZpXlSJWM=Mv(~ zvK{?O>AcXpbd}+hn{~*>weZwDTURX*M^9RkOO#DUfRW1;comKg1bn+mlsrNY8XDyW zgWg9~AWb_1^D8zsD4bL(1J4oinVy0Fimrh&AC}Itl;IH*p4eU_I;SWkOI!9tAbi3B zO@0=q#LHAc>z?ve8Q&hsF(sR9lgf_99_5Kvuug<^&0}Y&m)YjI?bITGIuh}AJO|>z zc*`Mly$>TA={AIT#d%JuMpXHDt($qkc*3UTf-wS$8^awqDD^|EAeA{FoeyJfWM@QX zk>vJ4L|8DU7jg_fB^3Qvz*V$QmDl*AXdw6@KSckh#qxjLCM8Nba!dTkJgr(S@~Z0a zt8%|W!a~3zG4Y&X6xbLtt^JK5;JT($B`_9bv(BjRTfG_Y`tg3k-}%sQoY@F|=}}${ zwmW%Ub6jPd)$;NA0=b7w!^2dE-qvI4)AVr`yvkabJcGwvuQ2rAoRlTjvCC^-$2BG} ziy0<6nt8;J67rymwm&wVZ8E7Krouv2Ir@-GQ%ui6PR42KHKms3MK&Z$zp{_XAVvrd znK4cbg)Ggh5k(4SlFOM9yyRUlVH1oo%|6Lu9%ZxZW28!c9Z%H5#E?B?7H7ulcUtirB<{s@jnS(-R@we z^R#{Mn$#JXd~5sw9rU&~e3fYTx!T&hY{S<~7hviG-T$<4OPcG6eA0KOHJbTz^(`i~ z_WON4ILDLdi}Ra@cWXKLqyd0nPi06vnrU-)-{)Xp&|2gV>E{Uc>Td`@f@=WYJYZ^- zw&+fjnmyeRoK-unBVvX>g>wO3!ey<+X#z@8GNc9MD}khMO>TV{4`z zx4%!9|H6k|Ue;`M{G6d!p#LL+_@6WMpWgF7jk*%$D_JB3c%D`~YmHRJD1UNDLh;Tf zYbbKcv9R(81c4yK+g+1Ril{5w#?E}+NVz>d@n48C-T-(L?9a9W`JV*{dan-sH*P3_Hnt~iRv)}ye;7$b}^4l%ixphDK`G#b!4R4qoouT@*A zZ)kQa)e94??k7N>tqoRl>h(9DFq&92=z|F!LJrh-97EoFL|Wt2v}>(zG1*#aiYA_^ zM_&%_G^g*O8x650e>m!#MDmwRub!irY>^^|L=!4^%lBr;?}mvgP3y~^mSdKSm^R~WAt7T0_ck0mA`GS)J^SYTo6^vQ|vuM7!92&@$BhtcQ^Z4h2)aN zh~EQthyjn1(eI~$FtuHH!|x(iHU{9k40k5nPBwB)X@8Lo$P6u81EeoNOGRct%a-LM_4y3Ts z7ki0PWAO^Es6c%M*SSRn)2|NAoUsKyL%))uVx7?5lkrk`njxs4q@M~x+8%jr7xV;- z|KC=g3aTZO|y|g~oHXB6b42(|J_&fP2Y`*;L07H2d>{~JP zFNGl$MYUG(Qy3dR?9Bfdg8#peGRiVP8VYn@)6T1bj*v)s6q*7<6P(ZVm4ZnTA;rOHSd>P`_5uT0+azWdV`gIvLaJ1o*DB}&W6LCgX|BycgF5qd z!)}dT#A~4*6{1=Bd5VV(Qa2h4x9m#2X711z(ZN>i&cn`BopG*5P`CD*HfYiQmXNGk zhgqcHPBrJP$Z@PLZ4}d-8^}%X^LtUDHq&;~3}lUyrxxl@|IS={GP&6-qq&Iy5gKW- zC@$}`EEZd}DOSeSD+v_x5r_tpBWfN0gDa21p(@TAIrgWQFo7NO@slI6XOAML_lN;3 zEv~}LlMbGWKu}0s$tO-vR)wD!=olGcA?}vU;lRu4+Zf z?nCD7hBmA5`U9P#W8-*0V1=OT-NI0k&_`UZ87DbpYq_=DBdyNDchZ<|V1f%dbaa7i zf~R+6Xt%G)VXlM@8REfP3u#7UPadWYOBMsQ56fHRv!0p9R6q>Rbx!n|IY0goLb%{+ zzy|5WXk+(d@ChzOWatIV1lc1F!(uEOfEmMd;v`|$Kt3X2Uws;%@OV!E86PN?CeHV& z=4#TX{J8RWaH`)!J<8AUs#Ar{6Am^8M{S( zc%K7y2YbcLUz+*eDTXdthNE)Lm^P&*e^eV zilOS9)TVKgr9_^_M!TJ^44v<YF2NO=h(oOr5jYxVTxWk0XJ8n0{F_SOH%49WMk*Sg7`g6B(=^< z*rLAW;8I5;1?;Fh{N=f;kxjLpj}u^mD|k8lih|G4#}wEG1j`HIG( z8y;BMR3cE01e?(+k8NLR|Z+)#>qR^iMZc=BkcixWSKYmkaHpIFN?s%*74kc&wxwB zrtbYBGz9%pvV6E(uli6j)5ir%#lQkjb3dvlX*rw5tLv#Z>OZm@`Bf2t{r>u^&lRCg z11*w4A;Lyb@q~I(UQMdvrmi=)$OCVYnk+t;^r>c#G8`h!o`YcqH8gU}9po>S=du9c*l_g~>doGE0IcWrED`rvE=z~Ywv@;O-##+DMmBR>lb!~_7 zR`BUxf?+5fruGkiwwu|HbWP^Jzui=9t^Pmg#NmGvp(?!d)5EY<%rIhD=9w5u)G z%IE9*4yz9o$1)VZJQuppnkY)lK!TBiW`sGyfH16#{EV>_Im$y783ui)a;-}3CPRt- zmxO@Yt$vIOrD}k_^|B2lDb2%nl2OWg6Y)59a?)gy#YtpS+gXx?_I|RZ&XPO`M!yl7 z;2IS@aT4!^l`Tped5UGWStOw5PrH#`=se%(ox%gmJUBk18PsN$*-J8S%r51Y$i!4N zQ!rW%cgj44jA~_x%%smSTU2WG_W0c&PB$A5*kl8{$|865+lSIX~uyDT`uI7qnS!BPAg1Wwrc0e)8Usf zv9^E38H&hWSp5!@K8Qinl|)9 zEB?NMaxZK^GB!PUf1TBw+`H&jFSNI=Q@v5$Ryf-y^#IuXO#vsM5R+9@qz#z0fD0GP z9|Hj#E>?<=HTcsF$`xn`je~D&3kF1Qi%dfH{sKh!~(IpgjkDGQn zQx2F9rv{*x2$(@P9v?|JZY)^b9cd+SO6_1#63n-HAY3fE&s(G031g2@Q^a@63@o?I zE_^r%aUvMhsOi=tkW;}Shom;+Nc%cdktxtkh|>BIneNRGIK{m_1`lDB*U=m|M^HGl zWF#z8NRBduQcF-G43k2-5YrD}6~rn2DKdpV0gD%Kl{02J{G3<4zSJ1GFFSXFehumq zyPvyjMp2SLpdE5dG#@%A>+R3%AhLAwyqxjvGd{I7J`Iw{?=KKPRzyrdFeU}Qj{rm{351DoP_;vx zMo*s+!Gwgn;${(LXXO(xyI@$ULPZI|uzYR%`>MmW6Hcr1y2aM5b$grFwW_(9Fzz$Q z$&8dKNdWvBkK=iYWA|0}s1B7>8J$g*Ij_+S9vC1#jy~uA8nr)yY)a+ zoJ=e>Lp`7v3^tQN<&6UpDi{c1b}F~fJ$9r=p=@U^J_7bOck$5}ncVjYB0yEjbWrhe@E`j64yN3X?=k_F3BalH$aN zV=94?wDNv=BKLB<1*xU|65Zl!%51r5sHQ?qCggCw;$2QfCZ$lN40WPL=n^{Prf^QS zjbZ&1MRGgiZ2T)}DpiluFr#q*!AZJ$1v#d10YQ{>wQ5px!y28-1hCZ7lwvQnQYN*U zOg9BpvB0A$WUzFs+KWk1qLiGTrDT-0>DUpFl??l(FqWVz_3_Xzqg9vTpagp- zZcJ!5W?|0G%W|AJVVHJ7`u6@<4yyqMGHj@kpv`P+LV<)%PM__Rz&oq~t-*vV12@NR zoEVPz<2D>O==MlNI`;l8Gmv49&|1`FR!}2`NLRCqA{@`imLz6zrjS4ui0)O;!Pu&?KPAcX)?tDPS26uKvR(ry(p{6kiXPoZbnQ!vx6dLu zZCaj~Ocr$h##KqsD;9;ZiUwhmUd%5lrwczWr1Yn6V>+IK=>51;N7JDkrm1NY-ZBes z;FxeOTb^HAyA+~P2}WvSSu_fzt_K=(m4wUp%c*^hF zEJ+1dP0{0B8bryXR+qApLz43iu?ga<5QQxTa$1gMCBq0W=4|DTv4nY4T*-^Im%>U~ z)98;hc(d7vk0zAML$WnPWsqK>=O-FZSLI3_WQKr*PCK=(i6LelZ$$}XXrD5cb~VXz zT%egX>8e;KZs@jcD>cL9VP(Q}b0r~ST$Mc%mr1cC8mqRUQc|N^9@Weu$Z|KeczK7HhSFeFV0i)MQmwrn7CBL=p`_9n?nh320m}6-MSv3L7I*<*56GR zZ`zI^1zyC7F#*zVL@M)F2+oqxydaiQz?|ODmqs|Ub8%&KXk9P3P7<4tM?X{~!;Ygw zt=h7)AYGDO9F&wV=BhCyD9exr#YM_-<;Fo~iE>IBEXK$%;JCUAEr;lR&3S_DUy_E) z#!oCYdENVE9OaaeaIrPk-odMtvdFG;ocA#`L6AifMu0og^?Oy9F|Et9q6 z8;3_|9+Io@hqYoN;58x1K&OP!9Vd#dzhTRjB2kI?%31ceHb#Q~WqJV5lw;@b>4@Rd z={z1S`d05YdWC*RLc7sR0bVGSytn-a3`JZL3|d8KC?vj_70Vi4ohP9QbU&Q4?Zjd0 zSZA?KbqLBsJg(qj>fycto3`zN-)lDe4{Ij-QfoBn@rT_tTszA+CnM~xWmE(4zfpCQ z;zPJfl3=ctrggYM!KQg;V{J;utMMF9&BfOe!<{wU0ph?-VQ%cv3B%fFiW?6xBPdf0 zD-HhEU?0C`G@7e+b-=8fj=TP3mdz&SIQ}Nd`*G#DTz9Y@b zaoDF}Gx7ZhPzpDhi^fA7WZ)EAEFv;N2*bKp0T za0t<^1|Zc#`A+?s$!$8eO4CK~PUFECC3BwNR4f)!V&-Y>$xg(%T{MtrH|CPcO(Lf> zE_meE1?6S-qlV^p2fh! zT11Ub)hHw!_mpFDMIAFB`%Yal+`1IXV>b?%!q^Ps%8nh8wtjVGlF-!5x*D29WJ4=M zZ7X(QvKe$YZNgM(HibD7+VO5Q29?@HzS?k$c|3B@JI6dlLgu5S&LbU4=4p-Yn||z@ z4p05vq*k*pbOV9QjVTMp8`c$?t@~!$8&5AP_sz@tk%a$nWHMh-Gm{WS5+q)5W6pU# za@YZXJCLTpZ}zb=$HCYbIm->?Hu6XIBz_d7)n1+3eSLzGVoNQCTHcu9qS2@({0sxc zu<-mhx@Xz_*(S1DEL|d0`YV7uNevL*Y6|DAQmvSp{4DzPL@>hqJ?`FjvIU;<&}YEKDmFUGSBYjRmK{Km-1m%-t=fFfI9kV|POH|SxvO=P+><+1JK_lt5F6fTPf8PXU+lYEJz__** z&>`4F2F8EWE+k7ZsZx9%!?A56{lsk1juYw5zN)V+g$d^Q^Gm}fnHKA6L^36=`e;p% zp{;JD$X3%}O7qINR*2<>a422}_hmc=)-A7B-1#2v85jN5K31t0DtmqON-Dim`XIR; zOo`KRv)gtn?stp*`^f>}UDnGYGnJAbl(4srd>(5fo2#oqi>#bus86EHfeItFIu$+% z;lE|3gjQA`BXHEE5JdcjCoethN`@NEc~zm6CYf@LJ|hT^1>l}gRl7oDHMnw!*5*IC z@@Mi=gO=lZSnWln`dX^4Bd{9zYG{HNIX-87A#5OM%xu*%V?7K3j3CHcN*t!zNK4N4 z!U2?a>0`8m8}UQshILC0g6-k>8~;SRIJ?vQKDj z@U{DrstWIT7ufyRYox^&*IyHYb$3wtB}V^0sS|1OyK#sDc%sh+(gy&NT9j4Aa7J0C zPe$02TylMjad&|{_oe3`zx)Cqns?6qThYue6U=~j5+l0Po4`bX*&9V@a<-O;;vCzm z(af&;e<^}?5$7&MRW$eb*P< zX|33QmDvFSDFK-qMz|RF|Eedum@~W zt~8C1@i8@LammTr)rAgKm8X_SczCg@+@LeWpcmx;VL;iLQJ;t%Z*|XbNWUnHX|o=Q z%bsXc%bw=pk~8%3aV-w(7E$co9_cHQ$!}Ep6YcoCb7~GQBWl#4D!T8A5!P*tSl4FK zK2CX0mjmosg6TSK@-E-He{dm0?9h{&v~}OX15xgF<1-w4DCypYo22%@;uRq`ZFld- z{Uqof@a@P5dW@kfF-`1B1(!R>(DHb&$UXY%Gd+6r?w8klhP&ldzG*6#l#VuM&`)ki z)f$+Rp?YYog9u==<#MC%1daG#%3EOX9A{7$`_(s#_4mV`xZaB+6YlX`H4{}vq;)TF zo~fR@do6EZIR?413A$V6o^fq&QV7P(bB(9m1969szOosyhZRYciAWXe4@u-}s(LeJpuIkSx)XvjXmvVEseG zJvWN4s|$6r;s(3F+cgeh4DMEq??h!$eb^5h#`whT5d03qfYpol8dCim)A^NG1-H}} z!b)V8DTL2Q8@R2p`y4@CeSVj9;8B5#O?jfl-j<$Quv?Ztwp*)GvQ~|W8i6?-ZV@Lf z8$04U_1m{2|AIu+rd8KW`Qk|P1w(}d%}cjG6cxsTJ3Y&*J^_@bQgXwILWY7w zx+z)v81rZv-|mi>y#p$4S7AA760X?)P&0e{iKcWq4xvv@KA@EWjPGdt8CKvh4}p}~ zdUVzuzkBlU2Z+*hTK214><61~h~9zQ3k+-{Pv~w`#4|YdjTFKc{===9Ml7EMFmE!f zH}U3O{Z`DuJrBZbz~OjSVlD6uZSEeNK8epja_LanEh8v;_$Eg9?g*9ihMoat$#qd^ z?;x?a*y3-pW#6|kF^<$w;2^~s!fc;3D~#&#WYZfK@3;bO{MvmN?>qy%_%v`BVCgfC zdwL~(H14Gr6w(1CX|R;zhZh%?*Q{hxJH`MV2)@Jg$pbqjZeL+LO7^vwgi!@3yn@NT zU91-{;BWIi8bV-j-YR|A9Qs?M?e7Ru&Onl1(Sz(kxAw?LEbd+Le%Z43rZgb2h2m|e z^rblc;4r+}?@tC(YIBB_qpQL?_kg{;zO#6JD9{;HSUgf@zIZ)}Bh4wFZIs>meSd}f z4iF~nD$KAV6CVEw+{YOPrW~~y~Y=?snG4dE3edN$~SXh`!c_F zUsQ1M;ARz&v0mIbfP}aLWZ&cBPU+DU{l+0}_>9DZGL{@}lF6QCtgAg;EWUu`D$Evm znblG}kC!}Mw)bR~U;+S}T9TVc6lXWR!LNMm)nmxr*ORkv#&UO$_WQpt0WdX{A=bjC zV^lB~(r;y!C4$Rk0fWUR|09O?KBos@aFQjUx{ODABcj}h5~ObwM_cS>5;iI^I- zPVEP9qrox2CFbG`T5r_GwQQpoI0>mVc_|$o>zdY5vbE~B%oK26jZ)m=1nu_uLEvZ< z8QI_G?ejz`;^ap+REYQzBo}7CnlSHE_DI5qrR!yVx3J1Jl;`UaLnKp2G$R__fAe;R(9%n zC)#)tvvo-9WUBL~r_=XlhpWhM=WS6B0DItw{1160xd;M(JxX_-a&i%PXO@}rnu73_ zObHBZrH%R!#~pjEp~P?qIj4MdAx@sv;E96Doi$eO-~)oUz%Z0Tr4K`-jl06Il!9{s zdjF*1r{XU?)C(%XKPm;UnpnDGD%QL3pgo0ust~+sB0pa|v37>E1dp*Odn)n=DY;5j zDzSAkU9B6F$;|##_mrDe#%hd7pC1u`{9ZKeDdtkyl&4>H=e)Fq@}$UffPt1#cjYZg zd%O%xpg4~brEr>AnKT)kF@`cdX4tMlZ#Vk!l1Xz!G970p`Gkv^lk-|>jmt0W5Wu6woGf?hNA zXO2?BG)<{`NsYAY#3|L^x*=rS7uWU~s<*UhTC8AYc#lGP-=Aw1I)@y(<` znQb^nL~$rlDbsdAc4nc#{+$_;Z4iY;Pi0i9Q;>ZB3+IjWLg_r40-Fso^xF<*_s7Tj zujFrMH{vW3PmCndjQIscnQE%`Qj|E2kidi#c&PcWIMyH+e#7!l`<$_)*pDP$!49pY6w!bN)j8~A1wV%gIakf+vA04 zV)_Q=QMPSj6$M2Ar#KhhxsbZUOq3nZHh8m0?Fr}I6N(Fk zkhXM(f57yOa8vn^97J+g9ISPa=-**6^8ZX&g=z+m&6~x<1>)MyM&tpbWhSf8#+Pcd4rVK#)NSw>1eLKHTO z44A@sc_}Ypi#ggFRbDRFV(IhOnRU&XPrQYh9`mVMo-^U$&AwsXooSRUFqJ7)XUXCK zFpt;gJ}9QTN9xy9$=3OnRkjgUuQZ`X)!}LBm~WUIEKuK-Z%}f?2?+MKucWU<3)>9G zxsz~2pHut1AmH<@66;LdCB9+dSpojE4ggrYS?%icv*Rpi?G0Q($^`(g<1&Z){O_5B$@f#;I2-+Qa1P$a@=u-vOY5vqo z|6G67X;*A|V86ZET9OpFB&02twZtc2K}~ASoQpM_p{vJ{-XvA8UmQa4Ed%fS{D@g( zr_aY0gKw*=2SIGznXXKFo$r0x3)@bq8@4od^U(L0-jvTsK@qYOWX?2G_>N+?;r{TU2{M>V0zid zB_Zu?WSnRl@k?oE*gsgv;jH@+ z-}BDGyR-ls7$dz{e( ztv7lI2|OxNkLD4zc3xGA`!d7LiSdOys4H!8aA(_c0Nm*uLjS4TW%Z3v>am1nwQ_lI zIs85Uufd;cv-(4wi(Js;QsL#|qdv)n;r_?puaK*1>zTC@d=#sK+q1YF_Q(5B%%3TtI8&bNs_e8vIb;oc|Rk`F~u?|A?jj{c={?{Env{mW#q@8 z)#WEgt4B6b&X2?o3=b`ilz;)-h$t4;hsxPDo-%5C(7m#c9tZF-U`vcx0HnVtf_X(}4Tg}4wx(=y!@T7{)4;I_p95mBhikg-|U9z35q`|!1+Zz@97 z(PFE5jCv|=t;^=(CLqYp)k90rV4ZSiFDAhD8YOCzv{}1WDuB?epORibW36);q(Aig ze27@D?lN-ZyjuB4GsebA$;+(KGiOtCe6Bfd%GKRty>dBS1GUe}MXgnu61UdgO=m1& zE(eECPF_%J-lU{;R)eQJot;;}Wch$-8Z|lxN*AAdc;bkpbD`W}F=Z}^Cy(SKyfF#+ zQSalA%JDDAu|77$M3E|kv==3vx~pFPw_<+9xgcE#oigh*>#QsA2}sTYO7uY(h@dhR zHJBi^bb-`1?<1cGFZJa8Akzs{H^$N<)5@hlXeKwt9hD5^5K&`pdHOI92p<7XhS?>| z(5h9KYctN|H+W~Xh2N4W+yjMyBm(AdewjX?PBuRU$^J zS#+U($K6rhFFzf z0q*kJ>B6xI1qAti?H@X@dxtB7_vT+Nj@PNxr?CSK#xqE6jh5S{`nH#zzvjOId=i1X zK(Yjl!7KF(73GXYLVkQA5irn|v-ArCqwi)CM8X&m!#@NQ3bqmQlfurU4qT`zl_m^C zhpk?mfVvy9L|)*+bW8&NY4lG$@0_PKfO9+~(zrbn?wECGi7472W{H&dRPZum^Qf z73C-TR6$#q>XJgYnUgV!WkbmRas;`TY#7CxPXIEGwT6VPBDKbyr#|C2M%q|7l#Ql< zuM}j=2{D+?SxT8?ZJn&Z%cRN8Gu@y(`zV(lfj1T%g44(d#-g&@O0FL5;I9=?bW>!M z%c3J&e}GThdean-<||jUh zlLP`UeKBhhrQ?HHjM3}kfO7Z=EKB%+rs*t+nuBoeuD2yk%n32SA?-s)4+DsTV7U&K zyKQO2b2*tQT}#((=#fkb%hkRkt^%tY&VK$hcs91+hld zJ%lgC!ooILC&|(Z9$zzk=Q0*%&l7wwyf%nv=`C=OcPjb|Q%@9*XkPGFrn+bxp?t^D z!_qO=e-;bnT)^0d|Ex9X&svN9S8M&R>5l*5Df2H@r2l)VfBO@LqeVw`Fz6TSwAt^I z5Wu6A>LNnF7hq4Ow=7D7LEDv3A))d5!M=lT3ConlFN`5eTQMexVVs* zH0tx-*R+-B@&Lp`0V4j6Uy=LJmLQRY_6tH4vnV{_am%kkv|{CYkF}4Wn6U+|9Xre$ zJkO;_=dtw`@aEs|^GlO-zvpp-73H;PYk}V5RrH83G4SVkRJ0YSluQa8pKejcqB4u~ z^9^lDR|?7vEo|jITtaIFI6}1;vTI6n(d0kDGQUJuk>>sqdd7#VBF;?_dM5i<+VMEq zc>habJK}_0eEsOkdwv48d43jKMnqYFMnYDU&c?vi#Fp+S)sxo1-oVJ*g!X^^K! z>z!G8?KfU{qOnLHhaEF4QRHgOpfvoo7@=FG(2ZefYJk- zZuA9ubiTTP9jw9Uzpx8FfJBFt+NNE9dTlM!$g$|lTD za4LMNxWhw8!AV(x;U`IV-(bK@iQ%#QSmq8D$YqLgt?V#|~% z;{ST}6aQbOoewMKYzZT@8|Qq z@9SNBu1UErolMjrhJW-Id&7y<0I<+Z-lr`IHMh1;M)n@g|hx_T-maO`s{Tuhax}EjC zS;1kdL*A3BW5YZXgD|0zm)g3_3vMs>5xgHUhQDl19lfQWMcfLTsw$)amgDs>bW*Oe+$UK^`ioL%F0Ua5vb%II+EGS>*I zw)AmqcWBZpWH&Aswk_FJT=J|^Gn=MfnDTIzMdnoRUB91MeW?e>+C)g3_FDN8rN$(? zL+kH!*L}rq`MK`KDt^v4nUJg3Ce-`IW0Ph0?|}Puq5WIS_a7iEO;~mGQqqo=Ey;ND zhBXA^$ZrCc#&0}dMA&@)&TCq5PMzgJPafZCg-6$R zRqJ2+_t+dGUAY@~xPzU3`od7-(8nnuMfM-4#u`Q~`l-CUGC7u*^5VwH`ot;Ck#R1% zRr%?;!NrB$w^}NW=GGR}m!3a9bh#wXrq?fF7j-IS?E_!GaD3KYzcXhCUHhjEl-6b# zCmIF#4y@HN=^#uIz zRFl8D)Ri1<(Kr~Hoi_MtXWP8^AyTKxi1)ew88bV{*Ok8w8YLXBFW0sRJ<(vU{$ym| zz)feLQbz3k;_}2_{-bW`h~t&2$ObtlbS?k2k|5Kbu?FZLDMTVW_Z6p#A)c)`3DD?a*hxHS2Zj zcIiebfsINfWvwY7Z{YOlIQ61b`j=%6{>MPs+`()Q{wq0z0?|jwRN(1IrMQsj40BHx zvBC_Xfcr;55&}MeoP_@#nz$avCh%FJfE5NNAE~fW@L7~f8Y=?Wno31128EYOK8+O! zc4Vaj-DCsB6CPH$?pQQVbb_(tg^x{$STYM_WKLtrh-_-Hq-M%Ubpt6$mCHY!B{ISD zz}grIo^bNVDw4={SA2*nDNq5`e@ZO5r4TbQpHM)~qfD9!s0h(Jf>vYd;I~j<2fD4)_>ctbwNX6S*8>i^*4 zYKI5<4}d;hM!!N|A$@eg09J|HV;!UUVIau_I~dxZp#?a3u0G)pts6GKdCNk>FKxdh_`Xu!>zO3Kv?u+W6cYJPy!@=PuY868>3|Zg} z$7galV~M`d!q(`I{;CJsq6G9>W0}H6gVY`q7S@9s8ak1r{>}*Q0JyH&f!f8(NZxhC zkn|KS64r^A1fniFel2KkxYByk%erCx9UgFLI)`yuA)X z8SU?6kj!numPNCAj}>1ipax(t{%rxU;6`(Nqt$~Z4~76TQ$9d8l`yJ}rniII%HbH= zlS_7o!qB{55at^>N!Voer%)`KMh9Yd@Z?~nc19*hs)NGN954`O9zA&&vJHbm&|D@E za(&z6A=3NfC;>I)hlI@ulP8E@W-ziGe{iCf_mHvWGldxw8{ng-hI({EtOdALnD9zG ze)fU?I(DNt)Bzdd9Cs^>!|+2!xv1SK=I zJ+y_;=Sq-zqD~GKy@{5(my&aPgFfGY&_mayR_)?dF_^Fwc-n!UAG+fQQGfjWE-1MF YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| diff --git a/spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7fcd..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/spring-cloud-function-samples/function-sample-aws-native/Dockerfile b/spring-cloud-function-samples/function-sample-aws-native/Dockerfile deleted file mode 100644 index 170191389..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM arm64v8/amazonlinux:2 - -RUN yum -y update \ - && yum install -y tar unzip gzip bzip2-devel ed gcc gcc-c++ gcc-gfortran \ - less libcurl-devel openssl openssl-devel readline-devel xz-devel \ - zlib-devel glibc-static libcxx libcxx-devel llvm-toolset-7 zlib-static \ - && rm -rf /var/cache/yum - -ENV GRAAL_VERSION 22.3.1 -ENV GRAAL_FOLDERNAME graalvm-ce-java19-${GRAAL_VERSION} -ENV GRAAL_FILENAME graalvm-ce-java19-linux-aarch64-${GRAAL_VERSION}.tar.gz -RUN curl -4 -L https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${GRAAL_VERSION}/${GRAAL_FILENAME} | tar -xvz -RUN mv $GRAAL_FOLDERNAME /usr/lib/graalvm -RUN rm -rf $GRAAL_FOLDERNAME - -# Graal maven plugin requires Maven 3.3.x -ENV MVN_VERSION 3.6.3 -ENV MVN_FOLDERNAME apache-maven-${MVN_VERSION} -ENV MVN_FILENAME apache-maven-${MVN_VERSION}-bin.tar.gz -RUN curl -4 -L https://mirrors.ukfast.co.uk/sites/ftp.apache.org/maven/maven-3/${MVN_VERSION}/binaries/${MVN_FILENAME} | tar -xvz -RUN mv $MVN_FOLDERNAME /usr/lib/maven -RUN rm -rf $MVN_FOLDERNAME - -# Gradle -ENV GRADLE_VERSION 7.4.1 -ENV GRADLE_FOLDERNAME gradle-${GRADLE_VERSION} -ENV GRADLE_FILENAME gradle-${GRADLE_VERSION}-bin.zip -RUN curl -LO https://downloads.gradle-dn.com/distributions/gradle-${GRADLE_VERSION}-bin.zip -RUN unzip gradle-${GRADLE_VERSION}-bin.zip -RUN mv $GRADLE_FOLDERNAME /usr/lib/gradle -RUN rm -rf $GRADLE_FOLDERNAME - -VOLUME /project -WORKDIR /project - -RUN /usr/lib/graalvm/bin/gu install native-image -RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image -RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn -RUN ln -s /usr/lib/gradle/bin/gradle /usr/bin/gradle - -ENV JAVA_HOME /usr/lib/graalvm - -WORKDIR /function-sample-aws-native diff --git a/spring-cloud-function-samples/function-sample-aws-native/README.md b/spring-cloud-function-samples/function-sample-aws-native/README.md deleted file mode 100644 index 5a4e5a0a6..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Introduction - -This example shows GraaalVM native spring-cloud-function application. The application itself is very simple and contains two functions - `uppercase` & `lowercase`. -Unless specific value is specified as `handler`, the application will fall back on `RoutingFunction` where you can pass the routing instruction -via `spring.cloud.function.definition` Message header. If using API Gateway you can pass such header as HTTP header. - -# To run - -## If you are on OSX Apple M1 Pro (arch64) - -You first need to build a Docker image where you will actually build project. -To do that execute the following command form [project directory - -``` -$ docker build -t "al2-graalvm19:native-uppercase" . -``` -Start the container - -``` -$ docker run -dit -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 al2-graalvm19:native-uppercase - ``` - -Now navigate to the image terminal. Your working directory is alredy set for the root of the project. You can verify it by executing `ls`. - -Build the project: - -``` -./mvnw clean -Pnative native:compile -DskipTests -``` - -Once the build finishes, you can deploy it. - -## Deploying to AWS LAmbda - -Start *AWS Dashboard* and navigate to **AWS Lambda** Services - -Click on `Create Function`. Enter `uppercase` for *function name*. For the runtime select `Provide your own bootstrap on Amazon Linux 2`. -Make sure you select the proper architecture (`x86_64` or `arm64`). - -Click on `Create Function` again. - -Next you need to upload your project, so click on `Upload From` and point to the ZIP file that was created by the build process (in the `target` directory). - -Once the file is uploaded navigate to the `Test` tab. You can change the input data or use the default. Basically you need to pas a String in a JSON format such as `"hello"` and you should see the output `"HELLO"`. diff --git a/spring-cloud-function-samples/function-sample-aws-native/mvnw b/spring-cloud-function-samples/function-sample-aws-native/mvnw deleted file mode 100755 index 8a8fb2282..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/mvnw +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-aws-native/mvnw.cmd b/spring-cloud-function-samples/function-sample-aws-native/mvnw.cmd deleted file mode 100644 index 1d8ab018e..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/mvnw.cmd +++ /dev/null @@ -1,188 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-aws-native/pom.xml b/spring-cloud-function-samples/function-sample-aws-native/pom.xml deleted file mode 100644 index ca936d5d7..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/pom.xml +++ /dev/null @@ -1,187 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - oz.native.sample - function-sample-aws-native - 0.0.1-SNAPSHOT - function-sample-aws-native - Sample of AWS with Spring Native - - 17 - 2023.0.0-SNAPSHOT - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - com.amazonaws - aws-lambda-java-events - 3.9.0 - - - com.amazonaws - aws-lambda-java-core - 1.1.0 - provided - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - - - - native - - - - org.graalvm.buildtools - native-maven-plugin - - - - --enable-url-protocols=http - - - - - - build - - package - - - test - - test - - test - - - - - maven-assembly-plugin - - - native-zip - package - - single - - false - - - - - src/assembly/native.xml - - - - - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - maven-assembly-plugin - - - java-zip - package - - single - - false - - - - - src/assembly/java.xml - - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-releases - Spring Releases - https://repo.spring.io/release - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-releases - Spring Releases - https://repo.spring.io/release - - - - diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/assembly/java.xml b/spring-cloud-function-samples/function-sample-aws-native/src/assembly/java.xml deleted file mode 100644 index bd4961b58..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/assembly/java.xml +++ /dev/null @@ -1,31 +0,0 @@ - - java-zip - - zip - - - - - target/classes - / - - - src/shell/java - / - true - 0775 - - bootstrap - - - - - - /lib - false - runtime - - - \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/assembly/native.xml b/spring-cloud-function-samples/function-sample-aws-native/src/assembly/native.xml deleted file mode 100644 index 805947c52..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/assembly/native.xml +++ /dev/null @@ -1,29 +0,0 @@ - - native-zip - - zip - - - - - src/shell/native - / - true - 0775 - - bootstrap - - - - target - / - true - 0775 - - function-sample-aws-native - - - - \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/main/java/com/example/demo/NativeUppercaseApplication.java b/spring-cloud-function-samples/function-sample-aws-native/src/main/java/com/example/demo/NativeUppercaseApplication.java deleted file mode 100644 index cb3f3adcb..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/main/java/com/example/demo/NativeUppercaseApplication.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.demo; - -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.context.DefaultMessageRoutingHandler; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; - -@SpringBootApplication -public class NativeUppercaseApplication { - - Log logger = LogFactory.getLog(NativeUppercaseApplication.class); - - public static void main(String[] args) { - SpringApplication.run(NativeUppercaseApplication.class, args); - } - - @Bean - public MessageRoutingCallback customRouter() { - return new MessageRoutingCallback() { - @Override - public String routingResult(Message message) { - logger.info("Received message: " + message); - return (String) message.getHeaders().get("spring.cloud.function.definition"); - } - }; - } - - @Bean - public Function uppercase() { - return v -> { - System.out.println("Uppercasing " + v); - return v.toUpperCase(); - }; - } - - @Bean - public Function lowercase() { - return v -> { - System.out.println("Lowercasing " + v); - return v.toUpperCase(); - }; - } - -} diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-aws-native/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/shell/java/bootstrap b/spring-cloud-function-samples/function-sample-aws-native/src/shell/java/bootstrap deleted file mode 100644 index aada735b0..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/shell/java/bootstrap +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -java -Dspring.main.web-application-type=none -Dlogging.level.org.springframework=DEBUG \ - -noverify -XX:TieredStopAtLevel=1 -Xss256K -XX:MaxMetaspaceSize=128M \ - -cp .:`echo lib/*.jar | tr ' ' :` com.example.demo.NativeUppercaseApplication \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/shell/native/bootstrap b/spring-cloud-function-samples/function-sample-aws-native/src/shell/native/bootstrap deleted file mode 100644 index 356bae8ce..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/shell/native/bootstrap +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -cd ${LAMBDA_TASK_ROOT:-.} - -./function-sample-aws-native -Dlogging.level.org.springframework=DEBUG diff --git a/spring-cloud-function-samples/function-sample-aws-native/src/test/java/com/example/demo/NativeUppercaseApplicationTests.java b/spring-cloud-function-samples/function-sample-aws-native/src/test/java/com/example/demo/NativeUppercaseApplicationTests.java deleted file mode 100644 index a6f2d1e13..000000000 --- a/spring-cloud-function-samples/function-sample-aws-native/src/test/java/com/example/demo/NativeUppercaseApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class NativeUppercaseApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/spring-cloud-function-samples/function-sample-aws-routing/.jdk8 b/spring-cloud-function-samples/function-sample-aws-routing/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-aws-routing/README.adoc b/spring-cloud-function-samples/function-sample-aws-routing/README.adoc deleted file mode 100644 index 6d0c545a7..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/README.adoc +++ /dev/null @@ -1,34 +0,0 @@ -This example demonstrates routing capabilities of spring-cloud-function when deployed as AWS Lambdas. - -Usually when you deploy configuration (non-custom runtime) with a single function it is automatically recognized and bound as AWS Lambda -by `org.springframework.cloud.function.adapter.aws.FunctionInvoker` (FunctionInvoker). - -However when you have multiple functions present in your configuration you need to tell `FunctionInvoker` the target function definition. - -You can do so in two different ways. - -1. You can provide `spring_cloud_function_definition` environment variable setting its value to the desired function definition, which could also be composition -(e.g., `spring_cloud_function_definition=foo|bar`). - -NOTE: Keep in mind though that since AWS does not allow dots `.` and/or hyphens`-` in the name of the environment variable, you can benefit from boot support and simply substitute -dots with underscores and hyphens with camel case. So for example `spring.cloud.function.definition` becomes `spring_cloud_function_definition` -and `spring.cloud.function.routing-expression` becomes `spring_cloud_function_routingExpression`. - -2. A more dynamic and recommended approach would be to fallback on auto routing capabilities of spring-cloud function's in AWS environment. -Basically every time you have more then one function in your configuration, the framework will bind -[Routing Function](https://docs.spring.io/spring-cloud-function/docs/3.1.3/reference/html/spring-cloud-function.html#_function_routing_and_filtering) -as AWS Lambda, and all you need to to is provide a routing instruction via Message headers or environment variables. The instructions could themselves be very dynamic, since we support both SpEL and registering a callback interface. For more details on routing mechanisms please refer to -[Function Routing and Filtering](https://docs.spring.io/spring-cloud-function/docs/3.1.3/reference/html/spring-cloud-function.html#_function_routing_and_filtering) section. - - -In this example we have configuration with two functions; `uppercase` and `reverse`. -When executing from AWS Lambda functions dashboard you can simply provide one of the mentioned properties as environment variables via Configuration tab. -For example, you can set `spring_cloud_function_routingExpression` environment variable with the value of literal; SpEL expression `'uppercase'` (not the single quotes). - -As for API Gateway, you can also pass routing instructions as Message headers by proving them as HTTP headers. -You can test it with API Gateway dashboard or (once deployed), you can for example POST to it via `curl`. -Here is the example of curl command - -``` -curl -X POST https://[. . .].execute-api.eu-west-3.amazonaws.com/route/aws-routing-gw -H "spring.cloud.function.definition: uppercase" -H "Content-Type: application/json" -d '"foo"' -``` \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-aws-routing/build.gradle b/spring-cloud-function-samples/function-sample-aws-routing/build.gradle deleted file mode 100644 index a641c315f..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/build.gradle +++ /dev/null @@ -1,93 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.2.0.BUILD-SNAPSHOT' - wrapperVersion = '1.0.17.RELEASE' - shadowVersion = '5.1.0' - } - repositories { - mavenLocal() - jcenter() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } - } - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:${shadowVersion}" - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - classpath("io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'org.springframework.boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' -apply plugin: 'io.spring.dependency-management' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "3.0.0.BUILD-SNAPSHOT" - awsLambdaEventsVersion = "2.0.2" - awsLambdaCoreVersion = "1.1.0" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -assemble.dependsOn = [shadowJar, thinJar] - -jar { - manifest { - attributes 'Main-Class': 'example.Config' - } -} - -import com.github.jengelman.gradle.plugins.shadow.transformers.* - -shadowJar { - classifier = 'aws' - dependencies { - exclude( - dependency("org.springframework.cloud:spring-cloud-function-web:${springCloudFunctionVersion}")) - } - // Required for Spring - mergeServiceFiles() - append 'META-INF/spring.handlers' - append 'META-INF/spring.schemas' - append 'META-INF/spring.tooling' - transform(PropertiesFileTransformer) { - paths = ['META-INF/spring.factories'] - mergeStrategy = "append" - } -} - -configurations { - testCompile.extendsFrom(compileOnly) -} - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile("org.springframework.cloud:spring-cloud-function-adapter-aws") - compile("org.springframework.cloud:spring-cloud-starter-function-webflux") - compile("org.springframework.boot:spring-boot-configuration-processor") - compileOnly("com.amazonaws:aws-lambda-java-events:${awsLambdaEventsVersion}") - compileOnly("com.amazonaws:aws-lambda-java-core:${awsLambdaCoreVersion}") - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample-aws-routing/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-aws-routing/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM z5b&uBBCA_wdL?^xw19P_F!l$XIUCIG0(Uznb36A^l7CS!0R}%?tUXwj0HwXsK4>8v zWE@fGYQ(q1F-!wr2v#*y7wWza-i5khqjQYc`6WHxhz85!iY%{Wb*z~zziBKpL+~P= z5yWtFJwj0m!TPZcI??gVUnnQOG_s*FMi>bxB)n3@mOYG~$F8 zl_Xm}#nH#t1z6WP61iq!0zB{Jh{o+KuI9xVM*x|TC7COi#tnUn_I;MA4`P!sk}}W2 z$gGS}m_|3n{2>Nib`R}0pU=AR9)Uh6;G*?1T2ZSB5`4PjrO>Bt2=i6u=qr=bN)Jho zMV?Wtn1yFbC*Io^`FFE6o|ePN6GG{zD$mtIc0OSsefFkNdF;nI-VNeuPS?6%IPVoN zZsFOKggP&tnTdglp;!r1nb~ME!H<>dW?N62A>Q1QI7WDZr;ehh?{L3L=pIMlpL9<- zCZ-fg1i?An;l=twL*C@`7quCoH<3MF6KapUt`yRJpF@_5T*SKkjpGkuc&h|H=`ud? z`ZbMU&m4ld%TU}+A+8V~1;8C{f84t#jj{05Rv(nfKmS(5<=Ac8!Twv+zNQ2KAo$N0 ztE8Q?i=mCpKTj(+=3sG#PuZ69xtt)EQ_E$H(y>G9(Tc1>K{$_6M z*(L~w^!?vvr`|bde{$}8^!2_!m&7A22>lTX_-4~b$zzFP^|OM2SO6_YC(5x3nDFZF zLEs;<=Rhe2kWFopSdxKt#+6GlvG$4b&}%<@1KN1(I;X?0JG+# zOZ+SI(Rz6pJnLxoojp_o=1!h~JgSvFTm#aA(MK;!EfdNVDQXa* z&OSYBpIIn<0tfRSotyL5B*mozW{+MLZ6NMLdlU~=0cuYk{B}v^W)@XIJ)rGX--$xE zOcvV!YR_%}tq!75cM%KJ4z>o<-#?T-I%Kk_LSFz{9lHk$0c_9Q_`|<#-aCblZ)o=E z*hH(RzI&AO5E03$9B2e^8%VO=Ic`s>OC%|BVCLoQQbv;^DMQ^Uw~-6%GO^F}H0Q~q z^f33U->p7+w08Mu`8u@@tTTdOW34aQ*zLPo3M*ZgM$1;R*;#AtJ6(i#%35VYXVR~_ zpR*$Hu4*h>k<4nGL6_ctd(c>3Fj`0BNeVt%XZj?1n3pFSWG&#xyR5p9Jv$6nTu7ep z?1&YWZQu<{`E%?dM-RU+EZMY2%EDea9xT>s>$*;qAlk-5oOIejvmMX=Dq4!!RUk=a zamTctj!;C0!kjqf;w{^1TIo=<;5h(Fc&cSFE^CdtNLq|vxH@9x>|8h1&ggl0X!ym_ zxDkU%TWQgqxL#tcz=HsPkx1(`m~!V*zIMr!EW@nJ8EsF5D1i?_3bVt6HC-~|(pC+o zolB0hY3Npl)MYwqOg)KHp8bH;7}-IT!ab|vHd#`jh;fZ<<}KC7PEI6)jPuAiRJGC5 z2&o+9RNmrt5uHY7Ei0NyCNA<4mLnKiFYNv_Zb#Nii3WTZ0arZ8AT4M0>{%QkfFKHD z$$+eh87@<>*<{1qeS%#EY7=9pnWpm2e2)YsTnSN=OZ;bh@jzvAJ7{9b^qHwKQXd&- z%P@H^nn=iub17MjB9)=GFUvK6%wfa84NFp5%?$!9s);AdXonKo1(r8TF-+CxrZNsr z&~Nv31)}ejFF>%}r3{F{mBb*6PpWF=m1;g?!&1Yw@g9xX(CztT)5@3!PJ$MraL?jJ zjIfepZ3R}0DTSdM7v5{g4CqqENzH&qX~|~OOAZ?k(03=3VqR=omosOJO0#<^kry}S zMOVziT*;@o#igZ%dH=|V33S4P3X#diBc9o-J2t^IYq9m{K7GEtHmM_yBtV6$dz7+GSDI~g-K~b{o`Ud#% za0>r2$Osa6KCfwq^?pc*f*-YeG33x$$Cz>r@k4A{>e&zlHn~AYPNFAkSGe@|SF%2qflcY{3Q}TP1xU;;lixI`{PI_{1MwPU# zb8@!|+^PX>d@Px~2o3tYZS<^mg8`s&^A%j$#_ecM)T0-=M6*JcsBjG$6!qH-)6k^r z=hP|(rciXq{A45YWNjc*3tE28s-&}Y*eX(?Dl3}SRu~$6>Iiz?;9=wGO3&_yuud9e zI;ydoyIqTk1TB7ZTT{o1+!@^A%5#rZX4&G?bC6Vjp}Q)V%s16{j$h#-0dMi5>oaC* zU7@wAR|uZ!g;*b6%$SP9WYJtzOSYZDh1c(z!EV*QKzo%BvfbkQv*RPPRQm&M)gPX{ zsGE;rsTtrJ$#Y-96Z*&W0@1o8i1XD}SJet-l%J+a?+-Q*x7&~$2T(*W!GkT;zTp0% zNA(Z6)VBxSak^X6;6eB5FV>%~$+vsI)VmXV3FrLDw`e5ziZ6n180=s3hq09zred)+ zgJxaVKHB88?P~L<=_F^?2OWvaMvl_Lf>sx1GE2t38EFH4*y%WGwX9|A`ZH11xDv-% z3(>w@i{-S_vscw(nT*5!zMm)OY9HA?0x+)$lY58XGTd?$B3bT8G>2Nx$&v++LtnP3 zw}ctz1peYD;s&U(-^Myl#2TRgMq>XF?%dT=NcS~K*x?!t!7>qNE z#XC*r*1Tmas=7$c($69)&0Q|gv4u14v;$|>JCPh{TE18`JLEk$4XUNT)N=8{H?x*& zvob>*k&1|Mkkd%B@&YU_Lcn6yuNS9U<3xC>F0xW3NJsSKU{z_OEIUWa!kVhos3p^e znKBiVqZGn&Zfiz_FCObw-B89YT-{>XtOQQPL1W`9eIoGH-yu`;QO593{jOJqGn?rW z=RZk&t9S(Xl|LZ(OCOgW*&y;4vV)EVx-q4}3kS|HZRW|V9K(LmDf^v;cNIA<6Xu;r zr&oQ^+#ynltMZM`QGV&B_LCdX;Ne^G^-p>$C`a&0*)GRI%e-E{tr+g{@f;iM4wUfPv7pnd_ccS(@ z4{d>u?2E(%@tJmuYw(j8bKAF*cbJo=l*&?B*~c9JD0L7D9LGrhr;Cdt zncS<5VKKJXK?NvGezTQjVUEao!!?}QQz%e#pJ`pN*=dEnReH3bA86g#Q&aLzn9ReZ zzJ$1Y2xzkQdOGVMvC7*9JIRk=IPkJQ2Q3hL%S@dl8N9sAYwsaPHJ_V#Ur9yFWa?cX zjz$+PT{j#E`o?A)2J@8F_`LjHqe`B}I=iKBH6G%zkONe{6sF|Z1v_YQ5&iJov>WGX zipwqW?lIMTBKC>nGA2tsNMx`5CdJY5t}Sz&K$ILDLDC^Pxs_SN&B&jwR}-G3CYZ?b zgKQIgD&Y5pU|OO#CgM zDGuh11j==SAiOZK7m6XE5XW7K(-=sL% zH&+Fz#zLnR(xemV8{F6vc-V`jR7;uVCP}E6Ih=qbmD+TbZ0%-$&Jvj$24?|h9`H!y zP_Tq~oX$EP6%+(9dat$vf8(7vrhU`tFbifgmbiJH(c??;^VknrH z0hsB`p0zIK60yzL%uq8HIxikY-MQKue-X0Bb=6c(wEk*{u0TF8t-_|Q3?O!7wDN;z z>J}_l#!p35Wa#!8&${i&4N1dhNxC7AoA!|VwT*p2*5ZBdic8_~ zkfY8g0D2OPVnL0=o~egN@WK#FU(X>U<#}TGn5vFj1{rPxmoMy%^)Wv?A{ASoTusuuqHD7a5BYf}yH8T5&ox(ckKBEO7Rd?Y?Lp&5oNE!c_F zq_zlC1$F{`-KoyC!}LT)RKJ8?u*ioiyHCbjkW@hWoNawAxb?(^dk1pHOkmE}1>J0> zG}DEB*XNnF=GEwAtr6@@RUF?=NFRWh9Yu~`=$C7-iLKM&68Z7$lSa2Q*@8# zr=^)HLw~**-4mMU9p_K_q(NUfgw!mT!&mU6UzRR3?O6+Kf?Bml+DG)4;NHTg#V->s zyl2!8bbaR#xq4a%wC5$AyIvN$3K^|=d2<_Bszp}&D?5ICjvp_Di}EDG=9VygTzAmMB#^O zss~=SJf03Zqu>_Z_sevE`Gw-k0H0vQK&)s_8m#@KSCn1IhS-8236Qy3u!>h&Myz`1Kd8B~HlYtAU=gA11kqTr1`MN9eyqp7elU7>IHRBL9eHY4UWJ;U)t{yN*Rm)~+ss$M3* zIi`3)<{@3Z1heF9@JR!C+xWC##A~Hh6;Jo%oqCK$fPG6;Q%&iwSVez+S&H&4Q3Lap zUzp_C?Bd3k@N0J(XK%I*Y8R~CI>_d(Na+h|_@M&n3!V+t$ONDV-MniLcA-)o=n`-A z<8ttu7TbY&f9C8tiFVKgy;}5p4$ktRr@!JYKa+g+S!26-yZ6r1b6BM82c`o(|AP?0 zWsdI&53A&;EqYJ|$mNdP4zuWK+h<-`H>2EvRYzSDeze~owhCzF^0Iu^xV^Sv!nqE-4@O&@C z!xw^61W&#Ioa2BSBx>;v{M8g!r2;OpS_^Wo%k?M z1ce90s~<)S-q0se_|)Ik!#!_j=fCxaOQcL`BqD`8@WsGWMqEx#v)r zTb_n1GZNvTYT}r9Ag$(i!8X6 zNU$YbD2sh6*}S%!#>qseXVzSBf>J|g&tP1*6;F(7o@z5yBV>-A-B7jDD$%}mKu=Sk zf%YTL_D!P3ujNo-A&!SXL@>`t8oeE<)7Iexa;)be(pOWnJo`y_%5?g?Bb{Z}ptE2I}2DbF^CCr)96 zZd?xW*TqH)B}#ln^QHMl0vFi9DB#20TVb)V^Qgcn0)Pn5QtC|S*aXu1d0YZVxclWn zla0V*_UL8ZB}?}GpxUEvE}5UU{g&yp2-u3POD?+vzbH_ZIN zRg;d~&1^c-`zGviyarVb*dbjO!waqeW4;Cq;S+k3wYM35$?xwUuWHYeBT!~ui^?u2 zDTZnl*=D}kWhrQysw44&$Nj-HI2T1J7ejOO7yPtWc&(=}{Xst2-Xpm5Hw^?R(nORl zSOwG`MxuD_>usNDbhm*wP?Gs$a<)_xk^J>MS8yA#9>Iynllll{WARg{G;EHXW5~Rm zL-|Z^83y%jy-5Zok}|{6-5&6+f3dejs1#g2J()gyET`p4#!=Gv&R=kKKGLVG{l$(k zuBnqP2gKL?<)D89(n(*PI=2Aj@{|2D7901rk8$xu|E<3{jctG{$?BJZ`OP_jqll%=o>SRg|iFp>7h4N6Qe#g*&gbN`CDKxlneuB#GKMN82a|&*-r|8(MUx|XCNs?v_@JrwJ}g0 z1b>lmV2^)q7zrPHc~=+}f7ci!e^K~w(iTHcLQ(?qQO+vdSOVfHybl9#9F<`NjAfiL zpzfSzYhGQp%_aHC$W(cOU0HnZBS5*)rKKjoVXk#yv8|-c70uVW{NZaZa+h72-E7fR zVcaym*Yi3l2bwmQgK^|i|uC9JmO6AKTOo5vSaE7!I z7ZHBuWomktl`=e+6bx-^L31&#i>t|oUVeMQkI}O>)vi3Otn+MRh-9msb!l8`zjS>e zMnz@@b3)gQ)5J>%)w9Zk?$$!iRb}du99&z~D;Ki_0S#o?vL)fjY*wm?^GxM${*Gun zIEbK*(gVC5#6>583s9<3>=)c3k{hbUdh)$UU|bAPFuY&}(krSDl(Zn43%S=hmgshs z=rhpKIIsC!BgObZ!2HuPa&6Q#rAL%7pzPV<=a#n$B&0YL-_V(;Nhr&F=vu37+#xim z{vkE!+&$}q(@;FxP`p?e9ZC z4vpX_#JUbq>_JIgbvIfvrRMIGnav%=hkdOyHPk2j&C_|64`1BE^$=?XOI`Or;6f`i z%+&w0(j-K^MUP-Qc|Xl$J1UgL%$O@>;R1MDR;90qh}(>`OjQIL#PO^Ud7^a} zKEP||e^%jto&@%3V@I!Aq8DlAuW`A;?t{==&x;q%Ah_q{ix0630P2@y;*klP4#WSD zaYvrc6eb!k*X9f+Blw4B+{c_A%nYIP2d0RBGh&eqBaZ_z#;*Yt=}#OjhOqCy=#yQI zhLnTKKJa9b`vB$(Ao&k6%Y3HIpu=gwm5)Ip7dYg$+zm3+8Nuv4&&&(s1N6d8d!kDL zlIe#s9t-S|d?E&24++OCMt$N4hjc`}+dEZx>O6oyo_|611-z}D z72Qwu`{x!>AM|UH_ypY=KYux@1-d~&Lm`*!P$2dQUO7(kmUGD(27|Z}pD-<%rw|?YSLpf58810bgRZon-0n3jtyb004^rTxa-a zKd7jOsj=&SJqSxx_cXv!#rz}NG-1cK6k?auMoCFSYP&ciI<=EVEUAn&zGAbORkS*B z%c8k{9kQ{32LVMvK~;o9gd!qZ+b(zk77BjX0nkOz|t%ZyQwv6Ar9!-%hi0EWRDop&s8J{t(y0 z909e1K0*rT`AAn#<;Vb(bB}h&+k}H;$ou5^)5N2{!G|CKe)3JY>CrILmm~o5W0!tN z9QZxM2S4Fvh-nIpfqDROrU(*+G56EtRg<3&eRzWdV<7qQ+Xp}&Vm}(thcbX3{5}<+k7`Q(^&cHM; zpl;S8UR>zsRN-u#ZSFLxXXd&w^ZzvKkH|Sx|QW;}y zwwjPUwZ>^iUL(>(T;Vp?Oug3rW|qX_4^=p`p$h~p-0jjdiZAZ8#u6qq`J`B(vzM0q zNULLZBad0hD+w7&%@y->WE`Y&H2F)MZLeV;-OxonwCUHW9SFHb;wf~iO&b;(Y@u? z4%$Tw*5v5}98V zAZ>y~BgD&16*=U&=dz6A*+(*dzh4#d=V|EhLBCRaXjJAGzl4-l>$eh+yQQ<~dAmqa zl9#Dzi85)r)=V+bZkEbESsx^rK}j9w%QKNhO3EVOuo4|as4O`0gg{%5M33={#iFwY zV;t7oFqNM>lkPhc4SLqt@NKudj9#nk@;Mm_B2%2BatkFH9*8KcQl|t{KtSjgY z*dyH1Y4R-;uFe>yuk6y09p9}tk*IiQ^&8^Sb@1RwZbDM_s%t=P>0%2-4+(#p&v01E za#7~6OOU}-)7YC^v^1Zg8OOp&zdawbSLKP_iyYi*wnEqBrE)tmr5bIJ9x3%`j7r}x zrGnd+LZ!r@`U&7y(%e?A*VWQee<0^6K6LGn9LX2e#T!d7ldXD>cKA|dyXwhakc>^Y zU|}vjw2zC)R^_3#xlE0`peQcn#`>Y_{xiPi0P;tf?S~YbRn&_m@tTckq9Zo#x#_-- zXdr7e1=gl};Kd#_?fo}C;+H;8`Jv}5%78(8)LH9o3C7p&40<_JO;wcAkjx!LfDGk8DQwau;V^g~l&8@j40GToR?g^-kw zg`U~VD4<;(?gO>o8QOw*o2eOY%b-hogBy+^-P~}9oIk8=OqN)mPV%ErQIVr$u9Zim zPWVp?=}kFPByX$Q9>3O3){Eu(Mmz!xX_{dUCp)ZOqg4dAitL=*7skIWF`qgcKR`=| z73~K%jpmF&%RNio5*}ZrrMQ@dS9P9qEzVREVS!Mjv5?wQ z$NUT#V;GsVUyHZuVn+B#;-QoqrCZjcW86wvJ2!mql*$(h9N|>;flzX+%cPISgz!D)|S2qu8H6sywRqb zH0|YusE-pxerVLq91EJ(4y$S#*5sVlS{7Q1Vm^3dsVzb!C&%owKGo#j+`M5C)`bgSG;KJ7N}V}!HM{-L%%=~hF|}OP z4B=oEPu$ARBWjggMLMW@qnJ2F=a@E5j$x(taAwVba*-i(rC~K~U~CT&AZ^_$pKLC_ zcrJm`yAp)aa#0pU5qG|83u#T|UXiQLGw56RvP9?Plv-;wZG0inQw`1tRbIDlZMG=$ zS|gNO>O<1ZoG2U9Lc!4dAc0qg5MG))j%e(Yjl)iQ)Ae*@?MLAFvMW%2jj zZ2vR`>O-0iRM!3s%B4PpaPN0j&1YI~KjGefFmdX8yi?5`G;JSPJLX19CW%R>L$-2l zg0ubJ)Vj=k4Sqv6*<&4k)JnT|?F343%AoH?&=Y+|^>*VWRx+B?3toG)Nif@!Q1Iad zAo=-XKjdoIpdAq?5jDKyD4h?#;w42Jw}jb;b*m9wl&veNO;Nd&u%acq5R)&6OCxD! zcTzK&>e)#3gsx=jR&3DNKxMOeUipkG=-Fjo@&fs9jJ;EIW!=8+orlHDoo3JJSd@`y+1I$tN#2dj6pE~%ELv|P#LU> zoiF2g3Sa$N)aTgCV{So-dAT@qt|W;9pT34JdcC5%fP$a_bA0s+=%|1Bqa8i?P%GQFXn@ny5sv z$hoFJZ8|eCPH#@tHZK+Tk_}5%!xkj!5;*zf_RumpDb~VeFVHCD+&r(RPP=$s%-meK zfpkJYx{;+d6gVYZPvz&>>KD{MD&A_eUz; z-J>?U)P~OOTL_uhm5ERMn+V;@p2SyC3*99lwtX+3|X>OZn3?WV`e1N zXMW#8K>SF|`4Jx?KQ_Q1E%qsv(Z^0Ie7$A+R*LA{#tw0PH|hO)PDff)ym7Y`Z*&E^ zDZ+Yc_Mo2gbbJf_&bLba=M&AU<83pI@xe zAfIp-=gbZ;@$sWxHKEQuk7E3cXJ^T7d}w9M9Z>>&r;O?BDyV5{s3_nYDCrkn+umNA zOZiEk0Wn2Ny@?YgUS$IccYX#1?rn3#Sd`=nY;)0h7|LD6 z4JU?z?sUhmpzmdYC~N~f`AmT&Mf)%bA!>^fQlb9wjItGcQk(q_d~vMLb==xB60|tB zEF;4Y&$XPOOxnP^N)nQpni)u`BLp{Cu{|h{TG373ctzG70Szai zdfAf((wJP2MV02XykIG=+?}sw7xYe%t{B6UaVTXMqI!xa^+=NHM?&0k*l~#_s6E4Q ze)jCi&R!#Bp-eV%!Th|L=U_jRTp9|PyePmbxDD~5)DLo3j)xuNDrB1@@7j4;1@$KI z^*3w#-=Vm@(fLKcGAtIFAS|eawsoXFid<^@6CwsQmC@&vsL}E_w*8+L5W71w3t^A!F zl?Lt|G9LC=8i4Gwb@DA@+6j_Ik?3s1w|^#r>AzP&-KkbuNJijd=jchdM4=1O>X)08 zKux(&W|)oV8+Rz6@XMlw3dvGNmfk3{DF$t5h*cZ3eq{q4TKgu1J`^u!)RrnAr7jXi zE+v{qGR{^f0gk4a7baDwfg;VSNLGH@$aO{Y&X>RdrQ|@vZEB2Igd-?QyEG`O^kZ8w zy)4Ycu&uY5osWQ{YPMF;Es_aEC@wWyCVHVEufUY#pd8om7#d$T)hG`-V-tnXBFJ*( zn^lHck;P1$k=Wq;AZ(qI6ugCD5*jA_21gs!uFjz*zZM<6srgenF)rCbeo%1*xT?fZ z2vyO1MWI!`SmoTHmLg4U81JUm*YJ%Y@;xzaF~{IC_pSR0M6DLd?BB4>FuvCtXo10OHYn7xB7?}dW9r^o3f0noO8z zF>xgry-GF@6OL`HwL930GNbNg_h<-BW7jz&8XTs|i)sx%VBH-Q#88$Icy+pX!RTK9 zcxw^A8AC{E;u3X*UM@Xm%5Zh}4W*!o2PTvgPls}qtCt*d^J&#!4AO+hLPy4-JZ;0} z)T!r7-3@^#<{=_gkS+&>QH>fC5Rq5jOx0K0-*8oJmN=xdepoqZA&PgVvptyZc<;W0 zX95C&fYzzwnx0%i22m7!auQA+@Zw=&)|kCx@Jg1AVo43 zIOTE=Td=~Y&Lg0d{(~LNCgF0hE^b-V8o3hgviLq-lg|e#AySvbG7Ir|PvIiGjR{X+ zv?YZl{&p>S#N{aQt$fC97*TabZKq+3|BUl zBFl@DF+;NCYxCAoK=CVxf{-T@@t@oJ~7q;_6QAcfWv6uFimU(pZO(^ zF-0ufSPgBLiQYW+*)U8s`<-|_N|@r9^hVDn@C2FKoQ+7sxSc7#yoFr0U# z{|=&N0M`8FhB)*yhb_{b-T^_m=Syi-sgDEWO zE3~Y^lESRO&!w-e?yzhJP2^EcEXmhm{^vN{o^&=(9mlO_jB{NS8<_S?B+k`|W5b8tCkk`ik! zP~h89#WaF*P$$MsOLBLn(4~TKt}W=VgxtUi9R(u{^I_s56?k)T2=0@3{ANXIJhj$1 zsop=_rnp7pnDsO_%p48jW7TsnZtN62+zodXtB-J_dq?mQYM3?SYMfCnZ&t9ZQ2iD< z%s+p%U9>l>s+z3c{<^B~NU2WnysqvAu(B6BSm2}-)mhB=P@bmuALR|h=r}|(Yk_Ld zuX-YtlQG&CU87jzYOT)lgk64hU*=LzTZYkbSx#1!+t#_VtPf!J*XxIbz7!^VP2&!f z$*=J6Lo)4DABzQsAIElQO5W@6#@P3G({;4-Pa$L6xcRq3uFsoqFWi7jS^IF~k-0Lu zxVf?^CFn-|oMv@(tH~H%C1qN^JXBO)Si|rLX%Faj^15i~>OA2)9`zw>p6#0-vw38w z%^KUDx&}Vh7|lSweto0PKO&?3qAF9EBr}9l>_qB=Tbxp(zu3ZPNJ$)AB=eC5uVL^5cMRB{MgKHK|1?ka5N82HCX*|`5o0^Kr*!6s(rJl$ zUi9}JvbAXx_uNlBK;!3`uKyRw>7UW_|3ai?sav_>E};Wga5TetCGoy|Q49fRB%)cB zf`|DgC-jxaUyzAdZf{stdw8BGh9z53oRlIDDYvtqbQZKI)r}C@TpCxalCuyY##ms z9Br^GU+*Occnm#%zBrDsIt_h!DmCg5lM{?WO}oZmK1#GmU=Uf>J0>3pfW??`@d;jn zQ+MxF&^~MjP;FocZ4pzt5>BK;j9D=SU_v)HS4;U`<7O~6pjxceCb_})9L$|h4?(&( zeC{8N-OG%~Kd~r-7HX~cdB>EC*?_3#-Eqh7hzH)|UkJf;3=op9PI;r0b!x>)zA z;p5gSir0i{+gC)(u2$}|Z&nu|G0ds^P~tNfwe%-N1+A&pUu2%1K6B~K-NJQ_d;V$_ zcb1uGMXEV<$G1CiS02>P_rkrV4Dx~n9G^cImHGw$V9}~FbZ(d9eJ2labLk9G=H42C zLU~ggxxVqjC)`8g{u8=@;$65e|Lg=#c%F(PU~+M6z^K1o%pfO$OTPFkdI5+%DQ2%W zLcxjI_rv)O{Wz@+Y+6_?kEr=uFZXuQZppLE$nmq#$oAl&KW)1a6+wb*6q|}hgE0z> zqwhGL1zL5tJzl_+XYpE6b!@0lDs7aK-ddFRex=`|#E@Oi?NT-ES?$rLr>qLlj234~2cbg)dCFsEaUxhCoE zww0TaG%V5#wg_G`j+??MojaIy<4@DgatbDG@`VVOOyd4xC4jX{iP@I_$JlVdg=)*2 z(wel+EVi;yhs+uJ)R}`lfn&}0E!WdnC@b9hYfv8jKcP`aN9|S#2ut9dNuaAKa=6ZAS4Z`GuXW zT8W2UBIBT)zI;ivj1_UmSc%Dey)IGhVLhSUhYTD3Sk_cC$;-$9Ev5Te;LeN%zbX0{nOfuo7z*QMb^k3f#%fd`zl&1JA5gzOCnxado&-u%_+4DYBck!@s#A< zk+9k$Z`H@otY;3_U7CjqPDmA~Z6qs)ly>|;OVFp%{n65d)dIb~SkElpuf-SpHMw6e zfRe=kPA9%ALxxC(v9t~*XxUb!Lq#RoT>@WK&Pvx^JwpqFPCo-A0CN7ZYHQ37Hcvz> zEbopS-zUWaMV8I(1m7npodZ2Z^lX5#$)>j_3`s}@$kC<(LFp>tphVF-2BKU@1qTUrnmoVYOjUiM)UZ^ozdL6Q8~hHW%PC5LhQ zBs_;iO|!EG^~HCyoJRKM&WNq_0+}5r?P?I8Zapm0&tmRc8s87)<#tP-$ZJZ(a@d1V zrTi`?sO#+ER&s94`aX7NxxV=uEvpK(0D_lnSq}^(YQNYr>R8_F_`!a@RU|5gP0jRU zlO>{4Qc=(jk!(>lSwNA8v0Hi5I3235_G;YA2U$n9lFR+kRXFd6HXAm@kA^(kvGZ@4 z$ZPDaAfmj`$ohP}c&48ls=w+4-QE0RE{3%vMb^UvI6CT+zQU?DjNh@cSKjCB-U=vx zH|Mqg4CH<{#JV(T!4M|g+Tr^ok zq9qm#qcJfxqQ!U#jEYP)A}z3OBrq_kM8B8yo)I~w%=|<8WUZ*(zvHPdBjN5%vDyX0 z-v)NE6UL{$M)!O^9^(HI0JZrqBhC!68-dhYu_v9*z0&A$uGwbqSy6J*~BQg z7L03dlL1HDWS`Pr^}s=9I3E^bL^ZP)jG8|PDdLFKa3+wNpkLg?TV{Afm399sb^47Y zI?}$f;mZOnf#RpzrpB71eCy#YID~miHph#Te>sBYtvRHA(;8Vr{hS^?_3R0#EYnRFnTZ;&44bWTgAcK-dcy~?t$qUrAwTw<7ryWu7g=J$OS(UT zN+cMOR%{Ss>N3KF2ZMk6HQI{yqNOU+paXkg_vATjx0A;%)t0=hBbhGG;bZXtU-|dm zEop(9oct!8V7R0PpJiHfMaI=9X%ZKKL<*)ttaxPjQ5HXJ1o5)KT)QDie_5&oL2HfE zcJ1_MV^vB0aBqIq@ri@}rZ!&u?4XAl=cL9_P`ADWbPVBA%qf^APzGsGm&d5MjZUY@ zX1EsL)!D&nc(T>&Tck+M{=Syeid4Jlw`cJxG$2QmnT!!h52Mv8)WcdOW^B@8150}r z%6)i0m)C>n4n;%AyjiCj`lf%!$JL<~ruSEf}2q{)TvJDv4E8I!H5|tKJ8d zN;J!19IOdr1O^#R`6BCqyzAlhDiLB6PTOJHHQUOiq}(f>Y*t6ZxwzY}FjEt@M#WaE z#n~pj9y}fWH=Jy^_t6GOB~hp+lW*3(wsQXGJiPs}lW+Zr#Qk>TYie2|9F~W{ib_ZH zT1|J=LCuc52_76NZfTyvKXP3JoCe)jR@})ZWJsw34iSF<&Z|t`Q#Gpy$T`Qn)!d>^ z4=Kqiqg!)iu;|QqpuuMX(#RB@(l-hbnL(mj}F2LsgwwtRm$e z;>p;v3>W6B5e^6~`+PV6rhEexRyU)}uq-#Aj-Q-@FgU}0363wojO?NfvC8((hnsq< zx7;u`!puGdHiIQ+L;!#+bAd4m2AjcxGY0P9*ilZL_j{BI8~b2ky3mqzf1l`FC+$8u zLduO30@ck)Ij49|NI>Kd^Jg;OqTLmD)nOBao<2L1H@N}yH@yKu5k|sZ!nEI!JKY!0ajCD+xk}j#bA0onRWj}^<*xn%QMxQG_tvgu+zmapC zKg6h4eVcxj;O%PZNxjz8a+uVpYmTq7NX|(GICWQj-E|AtC(i2yS<|sk8>(yv2o(zU zj*pb5wEJ`jcKg)mHDHVeWeqqLw07+TJk1Ox)A!m*?d9g-@P^#;0PVdw7#QsW7iyy} zt3}0@Ej5xGSXJ#8?waSy(&*hQwxb8{WK0($)xL_g8qK6xsn^ainS4zuEmZbOdqw5h z^|PAVR3;AP;dc*=J6QUSvmK=m+~rYlRaJ4A^KxbtZT6K#lm?6qJ$xh)q!{NROG+pG z?$$=`v=#`^iTiaa?Zo-Fv&gR%I@4!oT{&~hFa=UFA6!fYYJ6g_`hSj(v*D4I6X@;A z)CjUxE?Xrk(^xGf_%1Fn2wlV)nh7@H&E}?C4>Bej2MtO5A-ioUoJ`P4BWCv@d$osVx0k5HbVIb`K9FSZDdmXbO+FU(VmfcVWw?4a^wERqZ z0%yOzT&+d;SdVZzwXMwf`aGc)US&7jxIATx3cGD4=>XEr+~F-M(abJK7bklpZV6oF(x}wL*Q}q_dWDYFXW0)b1?@Z43nRbxCV<&Fg$- z5FIy<)2tZE6Om?vBrl$HSa-Wp^G!321jwK`v-Mob-y^7Wr;;k>gIKXnsB#?`-M`3& z!I{g=T1}w#e~r`sVg)HGwt_g0;@8SXf;o$Ei&<;SI9p%!lFwWk5I~RBMY(V zJ^K}>W3fAQeiny1_x`~z`%$e0qm~Y}6`l;0l4#ux8|VY!oHZ;PsP*omSt;HqZRWlR zB6k-I@<;dK)sTdc2zSs=hM$?m-^~Es)sWOR?&~$VR7V^0=p1sJJ#O6gK+sk+xJO>X z*QYoH#I|RmwP$GM7fJ(8NmE`?TV7$-95N6Fg?(O=8YS1@`V~sA!1@*#00^CUOvMeB zseSBQWczm@0~;qT8Z4+l{ASD_tp%RZi>wTSCY*M*IB}=uewB=4DI^v-<=(w zlT8mztmRo1Du}aho(8}ElpxB677Mry!i(F7DdNaBM|`X!w%I$ri9Q}LyS~Ajp1tjo z5d@{<-SQ-GfkSFb8oAgf76~s7|Cxk{w{wQ4+$YcHvamH|Z2)@I6+u;P2Ot%wirk_6 z0BvLwDHTiI;>XCYOwl96=;V|UqLYe|Of!o32>N0{&3^)D!Zb*I$(R zfAZ_;-2Mqxr27X}-u@GdLvR0o!0XD>Q}R?(lByDtvJ;aNv}2Pq`$~^fGs^a~luC@u zs*H>c%&d*f%xdV2kOq9Uy`STz8JE7=t04 z|CF{%DAr@Y5X%>2lqK!%QIWi(XNl1l)$|!TXi7M zo){E*mvAjx*_@2YqN)4TM3_l9j?ANMA$G{LD--m-NEYvxLk$dEQixD|c;r$l0cO%; z9CuTj9JPCdIdx4+F9Nw98zH#$m$r`0Ns%XF@;3?>C;t|8{OdpXeC_{J7~xa!{iFK8 zzbXqDSzG)^ser$3j~#tT=KZ8?DSy(onEw0if`)%Z#EqPV?QCp5A%Zd%wkDs%OxI70 z{(ptVlT>s+nfYjZU~myM&7n3`+p|cA1RV%v+kV3dxNR2FF`mUe|3-M_WJvKfgba_MxO;Fc&AQY{-4lU+`y=o`gKO z@ICM$@I?XcL%(!1O+t_EO5nAC*YmZo@Kxguz<<)stuPilVX0HqWt;qoV0*>*TMdkDTiha*-sp3LP?b zAOR`-NZW9li*1_jgwtdTTE4~v%WB6Xc8duYAwVL63~#=^IW(YJa^8x5iH~+P>WPkN zC&0i;uXnO<8;S|7>m)G=yOJvSoa<*ZrG+u0o==^}kM?ek*}4(?ic{`vvXFr43w;ar z{BbB}Lh7ph+Hgy(b|INkII#sn*o+=mRl)}KUp7CMB>Q`90Fy2&Ng^=6B~v*i_6QKM z!#Prs0gIjFfJ-uw;E73*r686I2YI;+A%r}Xw*ziLVOOV>8UNRL!@fzzP94t17ms+N z1{Psaw?E`6)Obyc4_2D5G~d1poou5JOHbvoNp|39im|J;g8UYgLvu5ag3`yKX(S){ zq9Gc70hE?Vr!APSQq0c(Ev81=@d6hYgBhBQCPiu{7i9R6~sH#@ZA%TU6(SX zrr+}Kl&!y-BJ&TEnBvbSc=CDuEu{Nb%l)?|s9@mu37!8hUp6>W@UPMpq95i>T5zt1 z?V(n}GYV+nqJ3WnT}$aKKqY_K)ARa=pepOM+wK+8oTKrHPve9nb;I_HcJoOKKO`j2xWK&4P9U~HBfTN9ymDTn-VlD#rFs8tq*4-s z!7u&nc2A!UH1B`!cK`idWi6bXENso>?f+Vt3p$#89@ua;`BxGnNmqVBA8q7ghP}P& z+&Gu0n;A2)i^wR{-=92yfk}?FPd`8%sWOcXs63Cc&Cq!}jQdWcCy`Hj+mEyp!kk?~ z=Y%UgoJ@YnB|r0$wbJ+x5MFK&Iy%#V>Y!q10xQ{41vP4FvY9B=ln4{<5F6ysx(kA| z2-67T!)ii~{l?rSLP`gB;Ny2_pdL%x{t4oM&RTuNQ27*1vEC+A)Ly!3g@Ym$uF%sv zdGz;Ws_}4Q_$Q13p=QGGwh6@brmB=Vf)=ga>Kn_KCEgo_3A^=815>iLxJpQfq*ri( z^Y|XdoYBPP{CCZ|2<2KA*`ng|)MTprb}cUR)+>JEiuH#nZ|Dr^Iw}#k)v~q|ZFB&} zmI~$`QU>h!WOG4lm+#L0k1Ov%WXp68Sk!aO+e>n7Zb%C_L?&V62_5-DO=eCRiaKT> z1NYs4Envw3o!H4#WM>iOVxRZlNI;_zi-XivwN0x$0sSQ|yZsml1zA!d@)#x~fxjIj%rIH1V`Q_i0LLMg z-S_<{yoFY@Tnt{m?~2hge_G^|t}fsVFDgP7yoCutdwQ`3(*|- zIq~rQZ+gH#o4)d=J!Nb5*+1+JKAFw`Rk$TfW#$vvjP}R0-Ne8q@2)_C81Y=Jr*~mw+j+EYB}u`1(rqd(w0R#&WWp|B z$PHMNN(19wbh-BdOX1-@n7Ijh#3*mVD{#;wTkl(yI#!M9eD#)sWjy&fw@(x5ULssc z#6>Gu$jRrwUxwn_gEl`vumO)I11N&ZVfDWl%BQ}s9}$wZv-HMhp3E1>l$S+1 zt-a=Sm`z;W)Gg#SL65?K?3ue{;hpnGxL2HMawPU}KlSkI=)EM`3!0h-`M1VpTO1Un zt#8Fb@jR`<1Qd=HqdW9-6C@#C2Nq@cB-v4+J%uun){c2M_^%}I^o*-#FTYr9^h-43 zDdj?@;uAB}7}?kqcV+8&;}d=*vj8ETVTa4~qwkn_5pNq(;cN(uj9JhKg}xLV@DW8U z5&`wU$j81w{9gy|ubJ(H6yZ+%Q{g;6I!tRD@#FBvz86bS^rg|D%46+KxhDCYi-eQXPn}=G!bT&Gpjc0)|)ThluVM+ z=yU;^n+MsOzky%x{@lJo?!Zr>!mctKY={Cy1ADoS14{S;Ui19q3Cl1QQ9R#O98g?i z0N}yWT&CcvIdHBSL!`x!&S(}zM-%>H!sV@F$A-jNH$gjtDbx=_q9Z8x0ij+g%+Y07 zxTC?a4XI%dXI%P7R4Mt=JHxb+=H_KRI>?PF?!SxS$))(yUY6~day9cMe-)vF7j;jn z^j5dsZoE#cmVHT73^Ec5&b^OON4fBw>X{H3H)?Jbf%ABWGd=u1368Iu^~*VXp=04n zMo{nKJv^GMg5Bj1QSDb5Q^ovidJ!k3kuD2-1+y9O1lyyl<8t~Itu3dP57=mD0M$?r zF_|?mSr(39<*?wo!vAj$`Cnf}0Mq3Bn;HB zaz{Hv_w6xG&?E-~1cUrkD@l(vc0&3RG22L-UkLb)D-+qcZr~;Z$-%Obwg!GNB&B@` z)SG2j^Qwbh_xve^D%82CSDXK9IbZ(c(c_iZ=XE=$iqFi{wIKso8z%7kIO9I+db8W< z_w?1!N4DRW?>t*cbr5dVxn#rzUyV>@u!%JyCGYM$^sM#p^mK~lC9#l5cAf*HFtelqM%$T+vi?Dh0-czyF$9rpC*i}W(F9`IrQ>+&vj!$LyHN{Jw{M1AUTy zCadsJ>96^;%M~g=`PfJPR=7u@K?y-?DZzO*H5O;C@d^ z^UJ#7VOEwcv(#7LDOcwX@(jO_?`<`LJ7=F%0$vealnikU{acm62CT56Ne4Fd6#MX2 zpRbTu#Is79%e0>CE;`bM&&f$XAx#cdY=<~u%lrclr`ALMOoo=W~gYcNZIV{~UEg$aF0*BD6^F2>CeNnTX}J9!KzadQ4kmp+W!BaJXAWmzmGO z;VImJY7~a)7kRBrO~zWZ4t)B;Jh+9b;g(<_o7%1VX$i6#*{`V}eE?ij+b(}oiLiM`GF^xIaP zh$cxnT+WBNek$mL4O0u>nzmnw0Mw~{Trdr=(?)WAPVQp;_po}s5wN}^eJAS~Qmv3n zmSXJ%awpB*#xD%JPpE%#cVaFA1$Kp^uix(!ZEYwRjai(QJT!ww zGyG{hjDm>Z>s9HFcECK{>|}*xjy7b+ifoK~1-#|C8j+Wt@+YBh)}llrKbRjfnnhv6 zdDEHg)eKZ@uedah3aW?HM3l+fg4Mf*#WlWQNK8^6ip9gv!9b*nA&ND&G*YXpSogV5Yzx zd}qFZR%m{Y)<1VPi>4-00Yj5>`)y0)JSo0OZVd>!t1RCe5?&9l)aPwKC-6#KD(u)v^$P!LaC`wg9Zg-Sdx>5z~nU0o?HDF zb$7RZ`MtuBQ#SVyCR*tyU<6W%o3|*}{8=h{a+J!f)14|pAal2e%%;%YA5T&a!{lOA za?wQd#H*@3cSY^y4<7rg7RRp_Yr_0F7aYPz|CwO9LOWj*Zcugf=w4djSFa4yTNE{I z(cYy1(;BN++>8=Mr?Ypz7eh;i+`!y;r&Zn%ZmE%1i2>GpS{t0GIC4T$p@3q+PP#wc zE*LhNu*^rzB)-#wUJ*?K=ZX-nN#G( zvQxf+5P`?FGw~;aN69qAz+_A#zBR(0qCM4`cOA^xMcR${(JNv2d=W#Ey}|BOE43@^ zHN$tzHPiOg+2~j8`wpql8y(4dWc+Zaj`SI^8%3_8G=iBx)sxbQi`)B+rYEVff8zop z3WJNP$Kq^*mAq@i{LS&j2eQtX@C@DuePG@#BMJ=oQi-2hh+VqMHnq8e7kDjPbmGIN z1DM>ZGh0;~v&FNDK3YQzRBEOLQl+Jzp9N`@ugd9G@vP^SRj@56z--J`3KJY99JRKy zcq9~z5-q*qL%haz1QXrR4wK%Q>^1td^)jMd&jv8e>*7K_;gsT8P^4R0s_9mFMjI?e z{EQ+}Ze!oy>WkC656{B!h5h7=x|Gij(?P(fAU-?SY0{v1ERkP>8lP0-xJcip^A;q1 z;5VIO7r)lPnQNMxIMs3DcyIw^VOy0<#!L`|W zQ%2pQrrgDMIh+z=vK|7^T2$*b>i``QW;o|~jADj}&?0yE2HbU)Ic*d3?62EeUF&ik z;e{283NT{q;HY(Vp8|+jOW)hPwQ*Hkw&Ghh$@C4dY-8-wos0eH1p@^wW>oVp<`C2; z#iNFr=3tMjl@l0@es*NFs$(Q^@(ekjU)*qQBnf+im!rY8bc@lR;=N#9&%u~M6vtXLu@~Fw7~zShp5_G z{r{-wF4YO8&viT>-`F<;=I_wRx51&5W603Ec_g7EMMbJ;TEX@DE8mp&PmBTSGKoKK ze&|S`$53PX`hV;Uuk=UZacJAScuW;bUlFZ&9W;8e19j&sh)*|LUed_I|VT!LOhX3N<96LN9k=NMEKN%O^5{6`td^m+$qtxeOq z$`^t9t6rAz5@7Nd$IbWizO9F8(eEjlbcyz;soC2mCtE&xdX7<2k}Z5n99e6*wMNRH z`{8FBTk)}8%vlyK^5I5=^II0Vwi}U5di$h~<6HI4Ookj-y*Fn9thFAlTXyx0d{i=e zsZ<8V*kW2=7ABT6!?kCx)AHZTjJUq;MNxasQA~D*+kR7dASx3QObIuD7pu$NBgZIc z9b$Z%S?FV2LfZgYTp&ue5jTF_WycIRU^W5Hk=zGJ4}bQaV&GG>S5z`DPCEt=!Uj z#*(`$O2o?LO6V2vwl7at z@QRC!_!E(eb?t8&=QxNCW0SJDE^1Dw=y*q5K%%iKKe$%Y9*?T3b|%3<52b@!NOT&J z%ASlb0J6cQv;;*cpgdKkiawC^{TNFOEXzpZH+O{U@O5MmQx08(+}!|Lm=T7h#+%Xf z9;>QH7%!@!wW$MN<=fv@pd_ASTJfL$R~iDy-|I^J&GG){s`FodubQ^gf*SIlM68KA zQB?TBT>>J1qpzD7poxVF&@JC3{0k+8b4BY^#Z}^TG>_(gcfG@PK2#kRAvG%Z7fw3A z4hoySQoIVU`--a>uhmNzCxlIBFJ%Mm+m`@as5+nZSZ&)$&9$8*=1bxdA3e^ z;Z1`dirpv4?7{9~HV5f$-KB>&U^W5NMuKAe(bH#T0kN#aU8IHi?zF?XBlhBy+fjYU zeWCZKTwK!~xj%nl>I4-2v4$O+P;~v^>eG(D?pt9zy zRCBU=@K~i~#-dc{xoLO(_pDV34(N7s?WFn2D_SYeP3ZOdh_?JH40yT}j)%?CrpChb zU`0oWPW@S*$G)Ibi z0o-p_#Y^7jWw=dEjzjvU+Cp|SD$WJDFp$pkZdnZlr?oX~c`~TW76Y|c5OvKZP@DwX z@9OH%5)9Z{z2CaI4YUONO*vX_2B{W*luoTGv<_IM*BiJ0qz#Z4U-%eEkshR~Fg$L$ zZ_o9TA3ck`Dc>Qoo^Qn1&DYX1MuXs~lNQtb8Q2B;7%DDiP7QmtmmT>VmOx*o@Ava} zAvYs=WAD-(QtwH`Wu2IFlV+Z!{0-PggPs8So3a2fp;!2vh)c`|rXN;9+xmnIP1>;Y zSo*uiR&Mw%KMYm+)StEbI7nQ#BdAqFyd8I=lihTbCM)+`e@tp{dl9B(cX&qg!Tx|i zHEegYsGD`^LeeoEt4+?qx$_e0m?=eB&^-$&f(;8`M*0Je~WfkLFTSB_qLr#Un;^imfV0Hb73uErgp`POj|0alOCq z2;6?9j1Mr;FKD$Y=$1vE+J3sv$+SNN+ZwNSl7*#zb=CA8CPVdzy(6~t73U$*VKB)S z8s`<>*i>#55d3z}vdkygSRB_t6Dry2Xb*vpN??c^+&Xw47B>M`c#MUZSFvOcxp)j|3z&$SR; z+F4&$!&qzrgX|iVBh5d$!(2KP9!K_ZJwgl+<24>IL-rA_$2y>yBM=Nt%6)pSA>}N6 zdUDMtMXA)g7bGuQF0TDFt{hI0j&j{0cpgC#zhe+YGGG@wHfo-Vj(k^J2(_NmY|f4y z?+@bh4vx|`r!dCwZ{nqY%i!F7A4?nkS|~JayO4&{OZwY=*oOe3gkg=-M=RkJteO>H zx9zre%h8!))600?Dc=KK5{9C)wfW8x)zB1TgL1jLRIa)gm4Pr}sSZ?C>Sa}FYe*Z{ zEN|>}-#clZO}+gO!+*NHnbtZpC7*6@@qbU={%utM*FNU|!%|FA()}xW%h#aU;3_NI zn7-#0NhL;Qi}vFiiTQW50N6O*XLd=z<*2EeDFxX_K~JH4F#j{yYeBdh`xg{A3s-{a ztd8UC2|l+!Z}0E$JIFu0jcZQ_hKfVtLu>#SWh(QTOvdG2HjphSPvFAcR7tJa4?IHK z_i`d>L#CUDiWycG*ZYN5-D5!pyN_d|8bF6EXdv_EY|Unqk`M<;_O}4aktvN3!BP(f zR6&mT&mw(KZD(uz1?}TJaohvmm6VG|V(?RKhW z>)r?39>@;pkaPt_u;Zn z=`T`(jm${Y`Pw0ZjG0Uy{rX-ce+I548vA_wL_#|j1Al&oZf#_zEo=>yr=mCD8p@x- zq;)c(^%Xja99ruciXiQm;EhtNOHQsTc|)*78aFwyHkkeuM?s71ODWI!%= z2v|m57c?QM(^v2Q8GhBo&XLYV7X#h6)j`eqjB(6R+=6x^k3=wcr|#4-kj+M?7<+U5 zw8e7p7VZ2Iy^ntDt7_g!F6YY@R8m~sXJ{j!(IBsTbj3DT;DqZUEjEOP}W!cw(XdQd{t4{@N0BwKhO zeeYB zVc&2TNFZWt5nZ~pRv(mNw3&)Drj=d8&|xNdkWhjw46#p5 z&?EOXo>8;KZHAKTvolyyERY%)Iq)!jvF1)L!DGm9k^}-I_dXjpje2|}0(^63ov+oY zR&?O}?)PwY71kIDZek>DCOW*=tV#3yX#GP0HBnl1VR<;JzpxB0KQMvNnOW^N)yRsP+0ZKbhI5@cghs85i$Ah~><{GmaoK>F$l<7@@m zkNf-6)!~Os~H2L#;zXe3dEjx@Z#c8XS=1y?F zKFIG3e)}7mPCFz@&LA+z7;#~M`-;CYqK`|S+3bCN262^o!+br+PIQlx3pFEMSs6pr*6=;25LB?-~(_9{L z;s!oQ1Z|C!UI^bwd9sS>Oi4MZvcJ0TAxFFGp2w(1t!OVzh;*ZFN#Q3V9*cpG1QVze zd_!ElcJk+yXeETb@~Vg$vS*N~^w-${i}`B$ibQI6wnDm7F*P?T=998nMq{|rK@F@Zm<3U5fGY`% zXmfVDmWWt{&b<}QH4l+yWm!L#gP*m-_Gr7(NsD9Js2@Y;?lTHE2c|9DFQu#eg|WON zj*MHb48iyGp_&zy*mN5nEq*XsWa2q5ty7=Pi>+&i5e5{Dhl+k;c<4(c-C&PEu#CAu zc8YVr>+DM_C**$?v4OEB7Ktd_2{{P0dNP_TyCE)-isKd|;O3*`C*#>fd_`_I>Teq+ z+2)^CZHq`qhRZ8W97J|DcipI)7)TM`>y52gDKDQecIrjAPxt~ zo^U*Bf?+AH-dGojd#b%dDvFGaVKNKZOEeI}O7KYekg5q097f_!`HbPoT$L!y-GNCd zfuOyJ|V<~p1&NNY+KF+1* zZOG=s*BI+0srNv0PV`44+OjL4SK=?Xw-2P-K%cvVEXvOkF4w{tXAD#_;kASq>DdDs zp{v*fic>86eSyX6%0QB%yzR-Vdk6%P zX#Go#)u;|e$@|xuz^JSIpu&Cp^gzpk%q<`%7Hj$JArr@J{h-k@-wqs#|!ZC8>KY#S1c$RQFW1-Cu({B=)HVxRsi2fV}0A7ruZiglW8%MvYmV={vSa>gxq*v zb!8uQfM6lpZxYLeQD>82Tnlo=Gnfa$JcoRgP$qlv<=F$pCQ1>*oX{rC$$l!w>V-qT zT$qeZBlGYE0z=h;?o3 zrBp6&42|3-X9WWM!c9sqJ4A-BRQKj_ONI85_C_Q3NN1&PmPq4}XTTzm&LaFHaHs;` z1i#;I<-ME<;-nx7eCfU5r{gIx9exFgj$2kb7h?C>;82T7^15Lf7izUOA67+i~zUjk) zP@wYF$hNr9`Dg{tazc^aAcq(`4G8rwb1S@0kE6CkazSzQ1)O zFT8x>g2ZU1TqglAUV;EjFe1OV=}%4geW5O>ZL1H^Bh$CAHMTQ$(Eqb9Ql9)@4zWyb zG;2E1bvLR#A@Ow0d3QPl;SxFmBqjor*U!LG4d%@q5&-(0o@+e`$v1D^u0%0UX|ScB z!H@+LU3W(tcSpG$uXf8VSD!I|dinghETh;ysW*3P9IS#}gGr{vTA{alfSx1=6}wK* zJ8E*6vpTLg7;Me$e#c4iH!gkImhvR4_TZg7i0Kpe6d3S4R2l31>Ni!JHxp-ynWOr2 zpW>J-nq!&PgF7w(k%>3O%FUry6XHHK9lGe69tCI7mU@@cbjtWKO)2t1d`!?XhSiV# zfZ@m0)T`C#N;T@Q4{c~R5yF-UhtiJA6ME+y;1sz|2ooqNRqEszXX}hL97RBNn@f*{|d*bZD zi={%gD9boJ3+=+CHW|j~4=l*wMv3eolu6AJ`Z~z!VCf7kUsf63=wz^USJV~}2P|Kj zFqnx%?#vyB;m*c3@pN5zAJ7tv zIPu7!u_;{rbp-Oyt3fwJ0s`s<#OWgY7rphnu}~G-NnyHHi~5{BHugD5G?4F0BKQH_ z7$5%0fA0pGBMr*Qi(}Ga__UJs4nG-v){Ta7nUjsiwDV-l%DFC7rQU> zn4KP9uBb1%TDmT}n5yr$UnM0COTm#{ZEhZMyOy`kEF7Ml);g|yxoJceVh)wvnSi_V zy!|4~gFmoaj`fu`;Xwxfa4Som^Z4yVVX*2ZPMV#uCMV|6%zT$t(hT#JacW8*=kC5j zM}W-jOM%U3PSmsaFGqKMUcT63+G0}MBuaz(gn=J9ZTvEFa;|)m1n+c{Y5N-FRthCV zoKv$a)?I^!*l@rwBuwh^jM->l(%r4Dm&p!_K6DEyT++Ts=gK;%X8SW_e+bmA0+cV+ zI+r|8wUBJBg#%tjm+h8(=9xwsnr&_Gxt-eJIg3`Nb-2usQpRCEb=N+GkDN3T2cbHtjVCS}!+3ye@#T-t26W&Ci0RsX6Cdu--aVtL)mO z)qg_eOlg_!8_9sF-&4mShPd60FPI zJ~~2%$)uN9F1(&Wx{OJ8Cd6tOs?X9pV3dXlJ9yfi$+d## zhb7OWZCPh1hg+BiM)E7M2Jm`Lb1h|PWM?goiy0<1ZZf8# zCa&0MK(xoe+?Y634zmSqXWP$wV8Gr;(I~~R@LQWTG5levz*@>-N`$TIf!M<`W=jUl zP>xN4N*L1owyb7uHg}|%q^LB&SiUOVjN_%_A-W$pl88eC0^hh4ydBMBsD_ofC~(cM zt42n&FhoUK4bmgH*b}Si2_cK^$3v|JvMe1$9f zu{x7OR(ixG`Pj-h>MH#XR0e9rey4he+PVT7*4cZ1&+q@c&(W~TB*&_8A zeqBU^!PCXx<8O($cPt=a8D=M(BG&~O5sBHI{Tc(q4t?2tjK66zlWxo$Y?wrQAk&Q{JeJP7`w$7e8W&?R|_(}%PXF1AOvt$rz}j3OFQwmJarzxTrTbVm@#oP}AEc=bMYx%IEnO>%?rc1D`G zb+45})SH3B4YK;;ZgZ1!fPhTAU`izo8fX|ELSyz` z%y1SDxxIF8BGOWk=L>a7gec9Lxa=kJ{_G}nu7^EL`F#c`;JQ5q5D;S%noB-J1ZK4g zA!u~LN$tj;>PfIo4u-ARk?2^})k27kO{Gg<$wiaRlU0_&dP5ySH;;Rms0x*oYgOwb+g}-6DftAw}7|73aWwqB*#0Fk%#g=akp-mZ*fc1z)Y>^KLBh`Q##f>rQ z-}MC*tYTl5?6lfgzD@HszA9)Jg#{0hJr`kcbh6^y8_;REP5o;10p*4{A#Z)neJ4ls zc7GrDHQm>i{fM5@2!43TE9(}k%#x3s?-f;fUB+lVeVcX+v(N^)%Q2CUVxWvR*P1Hq ztde+%o;P*yp?+CoF3Y{J%gcFW_AlOJp1JLfOgiqO@C#^@fOAJr&&x%Hn*qL5ptsfs zuQ4#AJEnTW?u62?WYLRNvTS{s>Dx4ptHdjk5XXtSdW&mtt<=~mx;e0@Cl@TJ+RVQ~ z?qHXcrGmykp-G^^&~NhCBF&sSK61RVw4^dSqe7G&Dxt(4zd=m0H(6KlK^yvU_;~Rw z%|K5e5ks|gb{MDEmT#sy5DlhYrFmPkBb>Gr0l(a8CAo}1f|Poak$l!oZQePUiQ1uZ zDY-Sj=>k|2$2lWkE!Kw@Pkeb<5=Rk#-k?YB66SsRBC32p67zXLiIsYbravW26gniE zP^UQf4)x#`Yka6j8EfJ2s6z;ML5Iw9XvK*}t90VTh3x3E(M$el^+Y(>&s&7nY`S~H zvO-2^RU{uJSa$s@7GCWkuYvDp>k1YI`uc?7)Z@PuF(Aq`A3HBmv1LwlJ3fpf54(k9 z#ms-#vRG=NpC0`@_A+0kkN6p6`^}VTNcI{37tZ_ep3pK}o-68s4rqQC2$*Mw`*f7Z zsf?}!b1zG?$}noMj`gH*a=XHoyYD-EWb;f7UU6j;Ym^lqFd76Zshwq(OcL)-*D<*r>u&zKlR5PU!Ub$Q6^?!y|+2b^6VOSt-_^ z%Zj-Kwug+V*7zm|^-FH%If>ATTAX%Y2v4`;K3YdBfAuY*jdSIZdth&*-na%thggU> zP55NW&^X>@q{{1@91&BWP^0ykyA)$7v^*l-h%!9acAw`0CMETx06Yk#7#z8THCA+7 zhUPF&qhd0}h4K`maf~H-aJiLv1LF*6Q$UPNE#MTmqBsZAE**)!*B}OgptX6AFlbH` zelmf<&@?UQz0J^Ih~f)wfk>SPh`Xxe^0mjV3yem;!b5_K zkI%6kdAHdv<@x33tG5nv1oE{wa}q>mujS?BRlQt|r39Vv!+WOtjvcSZ+4BY6Ub}eY zTaMje$@;HO3L4^Vkbg<B<2*zN2goBm-=O4XuI)X% zz8YgjIC}QMPWaXS^%mVpR&{YJt3D!y0YvG}?3bJEHi1&w582Qa?-gh{CC8h%AzxQq zy0%a@4Tu&V(W81d;YXNj=U5SLFRQZy zcfd)~HK@`fUIVR$Ge@wFD|9>2YRaIGqp3+MM+JK>8dKZLGigfG+99ioRVoRoVslF# zUm$_*H`j!FfE8U+2;sj5Ps^r{%!G){lSvojYDmo1kg!e{)m#$eawb0BFrOMpvm-st zE4~3bUKcf{$4dbq;}I=4i_+P_;=@A72OQtmpG1$@Z+u^ck449?ZOtgqVY1@ zZ{+Z~!Beiu8ARl`GonjbyIZ{;AYB-|Ic*t;Fw5UH66Tu$L71&IVN2jhJbyt8ssWy+ zx&@ttD$isCH5DnDR49BffwHnzO;I)ANC) zqJa+%=sRO~U-7z6>44p9f(o-b!H}`kqdQ`HeCWOL)NHn# z3#r4>m3ZUNbbZ8LV;grw{=x!j{nk}jl*AJdC!ymr(jA)7k^G;sgLduwG1(3$&BUS6@z zUh0GLzCvxTO~N_kT6+R&_HD=U$IC-^yI{#ZLn4B$OrtpNPzNnYu)JlGebSoAke5EP z(|yL~wczW7k}q&ua+zxN(p0h{XNtEaZj!t^hnDDG$;Sd4O*Msc*C1l6A&8wABG$!s-l)&{$j{CzLL{$%t%8a?!@hpW!{iWjf>Yoo7&hK0?1+v^3&y z&upm#Spa!u@s;{3_SKFk@3T90D$j8HT$j_XI$-pnJ>Cvt@Fo9`Y5SSwd!D{C0eA2~ zRigX#kWuD=`g*hEgNM(_;~R>Wg-?Rv$IJMlT^+(j35&_)LT~O1YYQuAqk+Xx4 z`4!k>wiaW~7pr$8UyIR9jtj1LK_-i_j(D&E-S>K^Es^9I(%H{|quk_fUgw4=P&L2P zI^jclwgL@I zdvSq#qc{xFX@(SE7zCq_{GR1L4(La2c|HzoaDIqXWy|ca1$miYg`gH>Nix5p-6-1- zk*@|y-JSw;V*CLbw`dN$>57KR1!tJ&%&@jw(lkFDBB^A3w<1jD8|{#Q!?3 z%>XaRcyw7XRr+3S1RH@dXwNIbnm{#eR2H&ej`zEwwdyEV}2i}E` z*{yiz!bZG-S70@4O}2YL3m<(S$ZFVpEpW#!a4k=GpPX)f1J5&&12C*o0ye^#{)MTE zgx>%VPv9>%2;0BxR;BO$&u6;tu^#(y4-A_k=p(cbA9P$+b`XP{8^nMRvR!ZsgQF?# zbQz1I@EP%qrW;|fM0PNK2fY5v`r@3bXdeb?myaCRORF5aE4GUn?QLIyUiF56p-y5| zCGL}pD>D=mhC9QOp((^E(lBlvcvKH?7jHPRb~*K+!&VbEY%drr+Ygg#)R>vtuNwLj z+76wiuCaD)*;U<3y(4TrPzRwC>$-EOHV7?f*@@9_*qCip-|mcd(USsKmkA~G+|_>@ z+Gh#ecb(g`<6Ng=?_8`OYl0Vs6N*VjNVaiEd8iZHUOtcg44r?mpPo_Exo6d8a$Bow z3BqraMah5_^R))Eo{eTK%=0#M!S@ZF^i%PRa>k6ASgfv5uH6zZvO{UFS0g`vyj^KJ z{aQ$NtqkVqIvtNghbP{n2u5FmyPg<3uw8)~mj-%E#UzEJ59wRCZW-G2wIjNeVPTtz zE_9eUu*FStC}J&xdLh$f+&i`TF5xk_NRNS8tw;@|`chYF(@0;&-=5lb`oDBMKv8nZk_Bn;-R z_kk)ffhEmn;VKZG<=I7$_-~yzU}T+&u$ab}xCx7_7MR!sK7M4L{Za ziY3XMotWpD>CIu({=}D4bll)52GHkI0hvWyX=|=123Z2G~+6Oe6;8X%oW2>KhkL(BxYwr)y4F zz3F-$z5Umd9m@;Fqw`gITq}^c}ShpKft<&t#Fi5X{#66orY0f}mq9sVL zH*2O`a$4`;_ZWZ5F5vL_U}=7%jdqhF3BvK%i+}YMESElo+jdiDImb%~kYhE|^wpYV z9!vJlBCa~cb2Zu%R=rTRC3wF#?BV3klJX(m%<(U-XUsZ>-i4t_e)Y>2DBm=7>IVv# zMW1ly$tX$|KAQAlRy0P#ghKzo0CVP|3BsS%RKxd4?JVZt9!lEM<=#WHrDl7q&y{Le zGAKeDgVP2hdM7%921ZA#(8vj(3`GrtyquSDx+o)f!?p&}&WFmd8jT$T;x z0ZcEz>y^tj8;@}~m6yq7NSMPSCk1yOPT(Z)0~gnlKE|PKW8U?}pmQ_r64>~$V>$IXD3UmIY)&R|H#^@?lB$Ry3=4u+4VVCNa7WV4s5o?}>7y9N1iI6^pNX6i!4 zXI^voflM;=zo!^_oBH_{4hFdaj6$|fdoVU!XKT`2$eiarh6+PFakM0!_8N4)hrl9_ zh(v&IoM8YSxMWCy4`S1Yso$-X~g7AWAwNqd|hG5-WL{GUJcQm=1cq9A{$Lf#)gT~ z#S;v}RO;QiO)(hDC)^ssSZv1r(Ra|l?m#$^Z7942h>BuC0|9aUKCJ&8E9T#9f&u~q zI$|lJJix(7F(&Q!WU-Kyio>7+!&9&^sgB7QC(xj!p)f3($Joh2ahs8(8BOYx zBFZVJg|@m=8I@TmAZet2pK@x6WM{*>>9n7BZ6xRl?$h&B62@ zAckY(`YMX?u|O&r*<8jtvAk;Cfjw{Nyay{zjNU?Cqg-c)n_YyXV>FUb-#&y zK3}ldPx+zj3buc~F?v-Q+JR^TO>XcY!Pz#CE9ZE7!&9?UOPS8O$O`AGT4aRgy(3F{ zr;#VRyZ2%YK-&gGM0Vlb*^7Mr;kRntx|pYeh|vjhd~&@sZ{#Yev%8hAgp3%k&V+4M0v^eO$__iD zj{53M-z;|ZJTMnlj1_Mv$ZrrLoRk1zj%+AfG^lsdXVw-`ylX9k#hqqZi+?>p`Y6Tg<9Ydgr!N1wjyeIZzZj%xfsGG%lhUg7GP(PJ=HbS5Z$_mP|f zjKg_m5N1o<7Or8!>b4L}gUbg(kK zlLv;*vYe;dW%@M|3t9(sBJS-UsyEXtJ5rVr-y>JS-puI0-puMSqhe#sJwC8CW7Y9zxoj)blmO&LRZU-w})h;h5yZSZ%D#DWIVP{N~Zg# z=#_?B9}Y9y_~Lx#AP|wEyE_BB1w%d^BUFj{g^E@P1)(A2S%!`ITcIWxy?6_AO#zya zc4KpVV{>77{ygv!N3~hvOw)ANTM|v&Cao7(++vM5ustP*^7Fe)#ND^=Xlzm@+?cPB zHeo?BE{DxyRSS<*1**1HJ81=$_xmP4Uoh}k-%b6ba`f$#QfyiaY71a)CIHOMG`|mA zzd2?8eA*&hUj6?1CwG`x14fr-G(;|98 zeI#qU$qbf=5^@J@>3=+Wk%uDgmXyYEpLXiD%E8qB==S*REh06g-m6z~QiMJN@OShX z+1mjjDdIG_QC{i2v@~Sa>K>=>8>ri_x2keC+CspgkX(n&td;rmtA?%;S3dg{D*GMM zQtuT)b?ImgtwR|!c_jE$56}pfyF^rkZ8PSPNOU4;sq!2tujc-ge2U+~_SGYRS`w)Dhz*RzvdialDZ+5wRt(0}qn2 zHi3;aB><1wVEp=)HvtpRfDCf&cFD$@E>oXkXuo|IhE2jpxvd&DiCVLZB(&t>I z2Gc0APSg4QuLer3n>+nUzY@Ifcfe$f)Vhm5G;7%*dPRM|RM66P%$`42)3}@Drw(__ zxR??AVA?dWswDl{&of9HBZ=zxOu6N)ZGjxceWwjpabp3D+zYI#^>mW(ZhHrf-5>(z zlKK0ud!1Z7EBQ(e>e&Vss-K-0x%X5HGl~6cBC1u!7=oBMEp!!nvLi@oidDudLs$a* zUu}mQwo%s6tlw@cv4}CjTtiFNa=|c>Z@zqqkCnJ`ECIJr+ao_3MfgZ(Sh#`r9D}S& znTu;xYq?y9?bKdy3unJFiVQHS+U=)CB$8k?mpb*u zJfbEN@xULK<)?ig|Ct6pe1xFKfI*-VX8V1>k#Oc$5*DIvXULpq=TNsus7(3oe79rk zq5Nfvm7(M_>%r@cWv|lLsd|CaxnXMLgg2S8g;@CF-35QuoU2b;wRd)}53xJAM{(_NQ;||h zB=7)5}m37tuE{8(oj2!aw#7Zh`^kwqF7SBo?U?E?c zhJ=?;(W_A)!T__zak@fEch%1Kr(;gZU6Osh-_F3j8!N|}!oUKVx6oL9h?~pWR+iQq zh$6hGjH(m-+GwxCmHYzCy4~buN!shUZO(OB#@ah{(#CNYNR8Dp6~Ce5(Ufw(6Hn;Q z5r++5wA(Q1>Uo6}KBKqx$+QB&9w;=j@Tt9>V zTEBwhXgdc0k4QJb7s0;@V<(_*U}>W-Vr*k;CvUIwz5f6D`t4CNmq%6xoRY7yvaU7~ zgMC*wC+5qi1;Jm;hX9Qjg%oTa$2wOptui^SH#=`u^bl0ng%Tr4_pj_)Wy{f}$*#=r77`8Z=m`G^)G;3-= zk`1G0!HG1sB@lD4n2bssGhh{?*7ChzJntBSq$5(p5bD@JmOztt;HBkT!7MoNOk$~4!>lz} z8xvtfy`RCruS!rkSIcni@3=A&C)XGmU}m=-=|({tbWzDC2jSqHbVxxrqNa8Q`DnKc zSqBn26Jhr3G(**$f%YXph0JLOIf=ht!)wz?ybiOQbuvnf41Y1;bn>1Q6rG+-#eE2Y zm$Rcv(RhlvOUwQBOmfD9z@&a|650UOI+4YwFj?;*@+8a$-!H=nct-jun_Qq&5=1&l z>qWcKtdZ_O+Y~4l9E^{0rfr8 z!Z@;uO7|8#c$kxZSO3ao!PKri8SIUr0BY*%>iig*b4{leF0DePS~$mf>W#1GVES{L zvuj`BZ`!-1Q@g2&E;6Aexxzqwvs)(n;WOS}U0l0F8n79k6lewac>2?!$sT=pWEydI z%2=4x3D*?FR~PWo>;u=s&S&Y=jdSb5l&dAh?hC^e@A2?H z#k@oQ_`&_=`E%%rpbPSevfC+HfUwhxUSq5vL@np0$PYSuH5Xi?C|?IUnLw`TFKqC$ zvge|4qO}NDofooQ@ly8;f)8NBsuaU2SxDwM8O?lGLOB8-^b=G<+X5h^kjxp9v!mgk z9T5b8;JU|ciR)m!Mj%mba&CB8DmG;+O6!oR)Na*4Y!Em3$EuBX0ppW!SLyIp}tB3Lc5y#8vg&`qc7j%Pg1N~)&IFFn3 zSGJfh_`i-Ju|Ql&-#n|o0LEyJ-^XZqXIndc^M7MgNQ)Vg=;A{O_&8T=URyU~GA+Es zB7iK^?T;RXhW?uF)xJkE-efchGTEfSiiENcG=4`Q61g!#A%C}OD%1JL$C1>=7SEQp zXC2SX5(wbKiOf*4RQ*PP%}_Ii2|Nd1l6{2KTeyqjs~hSQ%Um$TTaj8u3~}YOiFb#}Vb@Tvt`+q2fwGX=^3*mQDXf1&E{)4eX7Aiqk-L z$Ypz+fe@%dCXg_2u4pDs_p3f-6z|Pv66R$_9#y5i_{<#q$0kmtwc{1ArIWT@Mu4z0 zhEqw|76|NL`dA7VH8Wp`c%w|kwA)sIb6l>;4FLy_W^YtsB~c;2v%RO|1ME0JN>J_S zR>J9{Qrr3tQZuwcO@o|}Smn1})OfMBXC=|u(SnZ9WOEf70iG|i)u4)aOpnwaL4Ivg zT2vz+a6of51B^wCzc=Ym)9!c2>fe@^@8nl4CtjgE$WWp{+jcA|Fe9_!(6b)6F=0rP zBqv6hLmI%lHuH5g#i`pa(%$jjZiJHY+<@NzzPQZi^?X5$C(`k+Q%~J?Qx{h~JsyCq zfciwR7FikRMzc*eF&${8Xqh3Bl+!P=XZ;jftp(`0K8%r;IB@UdX@%XF-BH}}xJoR) zCHR7z_0n86)xd7Y-*2h%RaUV}bkJPVBSBs*z4Van!)G)%LdDCjM1g7W^hwAqgnwoqFN{ahS1VOpL#z5IdLpx4sY^qT^T8S4q}i zcEch!1ldo-p-?1KI_Wnvs$Ctf-3%S8n>pGa-0tBB0)!Dqf|w_eP{)0O#H#q|0<0uE zD!djon5YCg61}*9dxf2>W&MKgf$<>3=%-RFrvwNF$I>RkHAoEmi=9bhMv9|z+bRi7 zizyZ5(e!dMF|4cblv$=*`sk+*%^u4ANwsJzLjf_Tonr2aI>$Oe&(*Q1L(UYm24cH2 zCaP^b#90;E=%BclGz03oP30NL6m#Ah)G38T!AykZQ;IOsp+iBbhO^&cu)_szTo}O9 zMv6;2lfXzf#WU!4Nm(Wrl|hOz)-1HRqf$zDy3D7j#jXxUx0GxXVNSlP)o9U}*gbN_ zWW8OB566+!z{GRsSgs;3kPwhW*Pm`{HAhDO6!i?|(D3tmT34uQ&$m{r^J(fd17VBmlO53H<*I809%Yxf}ul$Pr-T0}%fw z>^)$3_+X4=ji5Q#d^XuyB+uBNNTWA~pEw%78 z@58WKBHu!2-vSJJzvdkeAZq%Dyet1D%>l4=7#JJc1L9``V#)tG?|Lr7t1*Bo;Rd`* z^nYg@@T~E^L--@~)Akets709lw~XgG(>EyrG7bc&oo_?N-&c+I0_q>pr7R8qYb}i0 z9EP9*98D|$W&U<9>hG(@+Z><)@`qaZMfUE`#b;lsTgC>wVn={cfZ%UHz_Z4?7m(jS zU;<7B+G(4a{TXe!Ln^o%P?_%lmHBHs;RE``AJ7CWE$zPPZdgfc8(RR3u0PZ^o^}DT znR=2*K>s2J6!n{C!rxbo_X~jN-yfjAcL8B1eO>$igin8p>W7tETm?WC0H9L+4GDPG zc#8`D5%sT^;yd=YO#iteo@(y?4PE2SFY`y-@74O>hM%Vzhd=NL0R#FUO8-mK|2M_M zr?v4^Kko+%welZX{&~cCDx32I&iBoKX3y^f@E>Q;pY!)^ck8L@%@07-xBp!O=PAm! zRNr37Z`U{7n7^)X^BAV~FQxnz!{%w?rz$dkC$I4q`#tgBegZ$O*PmElpTa*?2KfO$ zsry^reuDk}b;?Z^FOFcP5z1MzXYCt3jZ`_`VV+PvwwpB-V*;5LH#M!)8MN=sPygr1=U}b_P?s@ zY5d9`B!Q0qg5;m0Sw1b%({O)3$a-Ap#72PxsJ&ATyQ!hWvYH`V0EcJL*ph@pSL< z2NhY>KT-XUx%BCl-4ED+>VJa$K4ARA2Hw*GJT>h9U>dCdjp^z4!%ubhKMM5J*!+Vg zt?@USpJ2Zi==jD1h7jz91(n*Rm \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample-aws-routing/gradlew.bat b/spring-cloud-function-samples/function-sample-aws-routing/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-aws-routing/pom.xml b/spring-cloud-function-samples/function-sample-aws-routing/pom.xml deleted file mode 100644 index c9a21c2d4..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/pom.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-aws-routing - 0.0.1-SNAPSHOT - jar - - function-sample-aws-routing - Spring Cloud Function Sample for AWS Lambda - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 1.0.27.RELEASE - 2.0.2 - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - org.springframework.boot - spring-boot-starter-web - - - - com.amazonaws - aws-lambda-java-events - ${aws-lambda-events.version} - - - com.amazonaws - aws-lambda-java-core - 1.1.0 - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - false - true - aws - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-aws-routing/src/main/java/example/FunctionConfiguration.java b/spring-cloud-function-samples/function-sample-aws-routing/src/main/java/example/FunctionConfiguration.java deleted file mode 100644 index 29ccdf0d5..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/src/main/java/example/FunctionConfiguration.java +++ /dev/null @@ -1,29 +0,0 @@ -package example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class FunctionConfiguration { - - /* - * You need this main method or explicit example.FunctionConfiguration - * in the POM to ensure boot plug-in makes the correct entry - */ - public static void main(String[] args) { - SpringApplication.run(FunctionConfiguration.class, args); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - @Bean - public Function reverse() { - return value -> new StringBuilder(value).reverse().toString(); - } -} diff --git a/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/application.properties deleted file mode 100644 index af6da4bf5..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -logging.level.org.springframework.cloud=DEBUG diff --git a/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/log4j.properties b/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/log4j.properties deleted file mode 100644 index f644d953c..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/src/main/resources/log4j.properties +++ /dev/null @@ -1,20 +0,0 @@ -log4j.rootCategory=DEBUG, LAMBDA -PID=???? -LOG_LEVEL_PATTERN=%5p -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender -log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout -log4j.appender.LAMBDA.layout.conversionPattern=${LOG_PATTERN} -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.apache.sshd.common.util.SecurityUtils -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.crsh.ssh=WARN -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN -log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN -log4j.category.org.thymeleaf=WARN diff --git a/spring-cloud-function-samples/function-sample-aws-routing/src/test/java/example/MapTests.java b/spring-cloud-function-samples/function-sample-aws-routing/src/test/java/example/MapTests.java deleted file mode 100644 index 289a8c9ff..000000000 --- a/spring-cloud-function-samples/function-sample-aws-routing/src/test/java/example/MapTests.java +++ /dev/null @@ -1,31 +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 example; - -import org.junit.jupiter.api.Test; - -/** - * @author Dave Syer - * - */ -public class MapTests { - - @Test - public void test() { - - } -} diff --git a/spring-cloud-function-samples/function-sample-aws/.jdk8 b/spring-cloud-function-samples/function-sample-aws/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-aws/build.gradle b/spring-cloud-function-samples/function-sample-aws/build.gradle deleted file mode 100644 index 60ca5c3bb..000000000 --- a/spring-cloud-function-samples/function-sample-aws/build.gradle +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - */ - -plugins { - id 'java-library' - id 'maven-publish' -} - -repositories { - mavenLocal() - maven { - url = uri('https://repo.spring.io/snapshot') - } - - maven { - url = uri('https://repo.spring.io/milestone') - } - - maven { - url = uri('https://repo.maven.apache.org/maven2/') - } -} - -dependencies { - api 'org.springframework.cloud:spring-cloud-function-adapter-aws:4.0.3-SNAPSHOT' - api 'com.amazonaws:aws-lambda-java-events:3.9.0' - api 'org.springframework.boot:spring-boot-configuration-processor:3.0.5' - testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.5' - compileOnly 'com.amazonaws:aws-lambda-java-core:1.1.0' -} - -group = 'io.spring.sample' -version = '4.0.0.RELEASE' -description = 'function-sample-aws' -java.sourceCompatibility = JavaVersion.VERSION_1_8 - -publishing { - publications { - maven(MavenPublication) { - from(components.java) - } - } -} - -tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' -} - -tasks.withType(Javadoc) { - options.encoding = 'UTF-8' -} diff --git a/spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index c1962a79e29d3e0ab67b14947c167a862655af9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62076 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 diff --git a/spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.properties b/spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 37aef8d3f..000000000 --- a/spring-cloud-function-samples/function-sample-aws/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip -networkTimeout=10000 -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/spring-cloud-function-samples/function-sample-aws/gradlew b/spring-cloud-function-samples/function-sample-aws/gradlew deleted file mode 100755 index aeb74cbb4..000000000 --- a/spring-cloud-function-samples/function-sample-aws/gradlew +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original 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. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/spring-cloud-function-samples/function-sample-aws/gradlew.bat b/spring-cloud-function-samples/function-sample-aws/gradlew.bat deleted file mode 100644 index 6689b85be..000000000 --- a/spring-cloud-function-samples/function-sample-aws/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-aws/pom.xml b/spring-cloud-function-samples/function-sample-aws/pom.xml deleted file mode 100644 index dfb67f6ea..000000000 --- a/spring-cloud-function-samples/function-sample-aws/pom.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-aws - 0.0.1-SNAPSHOT - jar - - function-sample-aws - Spring Cloud Function Sample for AWS Lambda - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 1.0.29.RELEASE - 3.9.0 - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - com.amazonaws - aws-lambda-java-events - ${aws-lambda-events.version} - - - com.amazonaws - aws-lambda-java-core - 1.1.0 - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - - false - true - aws - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java b/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java deleted file mode 100644 index ade13c608..000000000 --- a/spring-cloud-function-samples/function-sample-aws/src/main/java/example/FunctionConfiguration.java +++ /dev/null @@ -1,31 +0,0 @@ -package example; - -import java.util.function.Function; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class FunctionConfiguration { - - /* - * You need this main method (empty) or explicit example.FunctionConfiguration - * in the POM to ensure boot plug-in makes the correct entry - */ - public static void main(String[] args) { - // empty unless using Custom runtime at which point it should include - // SpringApplication.run(FunctionConfiguration.class, args); - } - - @Bean - public Function uppercase() { - return value -> { - if (value.equals("exception")) { - throw new RuntimeException("Intentional exception"); - } - else { - return value.toUpperCase(); - } - }; - } -} diff --git a/spring-cloud-function-samples/function-sample-aws/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-aws/src/main/resources/application.properties deleted file mode 100644 index af6da4bf5..000000000 --- a/spring-cloud-function-samples/function-sample-aws/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -logging.level.org.springframework.cloud=DEBUG diff --git a/spring-cloud-function-samples/function-sample-aws/src/main/resources/log4j.properties b/spring-cloud-function-samples/function-sample-aws/src/main/resources/log4j.properties deleted file mode 100644 index f644d953c..000000000 --- a/spring-cloud-function-samples/function-sample-aws/src/main/resources/log4j.properties +++ /dev/null @@ -1,20 +0,0 @@ -log4j.rootCategory=DEBUG, LAMBDA -PID=???? -LOG_LEVEL_PATTERN=%5p -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender -log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout -log4j.appender.LAMBDA.layout.conversionPattern=${LOG_PATTERN} -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.apache.sshd.common.util.SecurityUtils -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.crsh.ssh=WARN -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN -log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN -log4j.category.org.thymeleaf=WARN diff --git a/spring-cloud-function-samples/function-sample-aws/src/test/java/example/MapTests.java b/spring-cloud-function-samples/function-sample-aws/src/test/java/example/MapTests.java deleted file mode 100644 index 289a8c9ff..000000000 --- a/spring-cloud-function-samples/function-sample-aws/src/test/java/example/MapTests.java +++ /dev/null @@ -1,31 +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 example; - -import org.junit.jupiter.api.Test; - -/** - * @author Dave Syer - * - */ -public class MapTests { - - @Test - public void test() { - - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/.gitignore b/spring-cloud-function-samples/function-sample-azure-blob-trigger/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f17644411d6e840bd5a10c6ecda0175f18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7fcd..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc b/spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc deleted file mode 100644 index daddbd8f7..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc +++ /dev/null @@ -1,109 +0,0 @@ -== Azure Functions with Blob Trigger - -IMPORTANT: For a general information about building and deploying `Azure Functions` with Spring Cloud Function, consult the https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html[Azure Adapter] documentation. - -The Blob storage trigger starts a function when a new or updated blob is detected. The blob contents are provided as https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob-input?tabs=in-process%2Cextensionv5&pivots=programming-language-java[input] to the function. - -The Blob storage binding is part of an https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-register#extension-bundles[extension bundle], specified in your https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob?tabs=in-process%2Cextensionv5%2Cextensionv3&pivots=programming-language-java#install-bundle[host.json] file. - - -=== Usage - -For local Azure Storage development you need https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio[Azurite emulator]. -For the emulator you can run a docker container (see below) or use the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio-code[Visual-Studio-Code extension]. - -Here is how to start the `Azure emulator` as docker container: - -[source,shell] ----- -docker run --name azurite --rm -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite ----- - -==== Package Staging folder - -Use the script below to package your staging folder: - -[source,shell] ----- -./mvnw clean package ----- - -==== Run Azure Functions locally - -Use the script below to run the function locally. - -[source,shell] ----- -./mvnw azure-functions:run ----- - -Use the https://azure.microsoft.com/en-us/products/storage/storage-explorer/[Azure Storage Explorer] to access the Emulator Storage Account. - -Under the `Blob Containers` create 3 new containers: `test-trigger`, `test-input`, `test-output`. -Then upload the `src/test/resource/sample.txt` file into the `test-input` and the `test-trigger` folders in this order. - -The appearance of the `sample.txt` file in the `test-trigger` folder triggers the `blobTest` function handler, that would look up for a file with the same name (because we used the `{name}` convention in the @BlobInput path) from the `test-input` folder. -Later is passed through the auto-wired `uppercase` service and the result is saved in the `test-output` folder. -Verify that the newly created file in `test-output` is in capitalized letters. - - -==== Deploy Azure Functions to Azure Cloud - -Make sure you are logged in your Azure account. - -[source,shell] ----- -az login ----- - -then build and deploy - -[source,shell] ----- -./mvnw clean package -./mvnw azure-functions:deploy ----- - - -==== Debug locally - -Run the function in debug mode. - -[source,shell] ----- -./mvnw azure-functions:run -DenableDebug ----- - -Alternatively and the `JAVA_OPTS` value to your `local.settings.json` like this: - -[source,json] ----- -{ - "IsEncrypted": false, - "Values": { - ... - "FUNCTIONS_WORKER_RUNTIME": "java", - "JAVA_OPTS": "-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005" - } -} ----- - - -For VSCode remote debug use configuration like this: - -[source,json] ----- -{ - "version": "0.2.0", - "configurations": [ - { - "type": "java", - "name": "Attach to Remote Program", - "request": "attach", - "hostName": "localhost", - "port": "5005" - }, - ... - ] -} ----- \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw b/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw deleted file mode 100755 index 8a8fb2282..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw.cmd b/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw.cmd deleted file mode 100644 index 1d8ab018e..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/mvnw.cmd +++ /dev/null @@ -1,188 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml b/spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml deleted file mode 100644 index 257c94597..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - com.example.azure.di - azure-blob-trigger-demo - 0.0.1-SNAPSHOT - azure-blob-trigger-demo - Demo project for Spring Boot - - 17 - 1.0.28.RELEASE - - com.example.azure.di.azureblobtriggerdemo.AzureBlobTriggerDemoApplication - - - 1.22.0 - spring-cloud-function-samples - westus - java-functions-group - java-functions-app-service-plan - EP1 - - - - - org.springframework.cloud - spring-cloud-function-adapter-azure - 4.1.0-SNAPSHOT - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - - ${functionAppName} - ${functionResourceGroup} - ${functionAppRegion} - ${functionAppServicePlanName} - ${functionPricingTier} - - ${project.basedir}/src/main/resources/host.json - ${project.basedir}/src/main/resources/local.settings.json - - - linux - 17 - - - 7072 - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${spring-boot-thin-layout.version} - - - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplication.java deleted file mode 100644 index ce0ab0212..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplication.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.azureblobtriggerdemo; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class AzureBlobTriggerDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(AzureBlobTriggerDemoApplication.class, args); - } - - @Bean - public Function uppercase() { - return payload -> new String(payload).toUpperCase().getBytes(); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/MyBlobFunction.java b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/MyBlobFunction.java deleted file mode 100644 index 06a26c7f4..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/java/com/example/azure/di/azureblobtriggerdemo/MyBlobFunction.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.azureblobtriggerdemo; - -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.OutputBinding; -import com.microsoft.azure.functions.annotation.BindingName; -import com.microsoft.azure.functions.annotation.BlobInput; -import com.microsoft.azure.functions.annotation.BlobOutput; -import com.microsoft.azure.functions.annotation.BlobTrigger; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.StorageAccount; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Azure Functions with Azure Storage Blob. - * https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob-trigger?tabs=java - * - * The Blob storage binding is part of an extension bundle, which is specified in your host.json project file. - */ - -@Component -public class MyBlobFunction { - - @Autowired - private Function uppercase; - - /** - * This function will be invoked when a new or updated blob is detected at the specified path. The blob contents are - * provided as input to this function. The location of the blob is provided in the path parameter. Example - - * test-trigger/{name} below - */ - @FunctionName("BlobTrigger") - @StorageAccount("AzureWebJobsStorage") - public void blobTest( - @BlobTrigger(name = "triggerBlob", path = "test-trigger/{name}", dataType = "binary") byte[] triggerBlob, - @BindingName("name") String fileName, - @BlobInput(name = "inputBlob", path = "test-input/{name}", dataType = "binary") byte[] inputBlob, - @BlobOutput(name = "outputBlob", path = "test-output/{name}", dataType = "binary") OutputBinding outputBlob, - final ExecutionContext context) { - - context.getLogger().info("Java Blob trigger function blobTest processed a blob.\n Name: " - + fileName + "\n Size: " + triggerBlob.length + " Bytes"); - - outputBlob.setValue(uppercase.apply(inputBlob)); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/host.json b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/host.json deleted file mode 100644 index 10d0c0748..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/host.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.*, 4.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/local.settings.json b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/local.settings.json deleted file mode 100644 index adce8b884..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/main/resources/local.settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "AzureWebJobsDashboard": "", - "FUNCTIONS_WORKER_RUNTIME": "java" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplicationTests.java b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplicationTests.java deleted file mode 100644 index 2b9b92ad5..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/java/com/example/azure/di/azureblobtriggerdemo/AzureBlobTriggerDemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.azure.di.azureblobtriggerdemo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class AzureBlobTriggerDemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/resource/sample.txt b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/resource/sample.txt deleted file mode 100644 index 089443f7f..000000000 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/resource/sample.txt +++ /dev/null @@ -1,3 +0,0 @@ -Authoritarianism begins when we can no longer tell the difference between the true and the appealing. -At the same time, the cynic who decides that there is no truth at all is the citizen who welcomes the tyrant. -― Timothy Snyder, The Road to Unfreedom \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/.gitignore b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/.gitignore deleted file mode 100644 index c2065bc26..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -HELP.md -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/README.adoc b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/README.adoc deleted file mode 100644 index 395492529..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/README.adoc +++ /dev/null @@ -1,51 +0,0 @@ -== Spring Cloud Function on Azure - Gradle Example - -Show how to build SCF/Azure application with the Azure Function Gradle Plugin. - -IMPORTANT: For a general information about building and deploying `Azure Functions` with Spring Cloud Function, consult the https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html[Azure Adapter] documentation. - -=== Usage - -==== Package Staging folder - -Use the script below to package your staging folder: - -[source,shell] ----- -./gradlew azureFunctionsPackage ----- - -==== Run Azure Functions locally - -Use the script below to run the function locally. - -[source,shell] ----- -./gradlew azureFunctionsRun ----- - -Once up and running test with: - -[source,shell] ----- -curl -X POST http://localhost:7071/api/bean -d 'low case test' ----- - -should trigger an output like: `LOW CASE TEST%` - -TIP: To debug your functions, please add `localDebug = "transport=dt_socket,server=y,suspend=n,address=5005"` to the `azurefunctions` section of your `build.gradle`. - -IMPORTANT: After completing the sample run `./gradlew clean` to clean the hanging `azure-functions-java-worker.jar` processes. - -==== Deploy Azure Functions to Azure Cloud - -[source,shell] ----- -./gradlew azureFunctionsDeploy ----- - -=== References - -- https://github.com/microsoft/azure-gradle-plugins/tree/master/azure-functions-gradle-plugin[Azure Functions Gradle Plugin] -- https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-gradle[Use Java and Gradle to create and publish a function to Azure] -- https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html[Spring Cloud Function - Microsoft Azure Adapter] \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/build.gradle b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/build.gradle deleted file mode 100644 index 57488a215..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ -plugins { - id 'java' - id 'io.spring.dependency-management' version '1.1.0' - id "com.microsoft.azure.azurefunctions" version "1.11.0" -} - -apply plugin: 'java' -apply plugin: "com.microsoft.azure.azurefunctions" - -group = 'org.scf.azure' -version = '0.0.1-SNAPSHOT' - -java { - sourceCompatibility = '17' - targetCompatibility = '17' - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -jar { - manifest { - attributes( - // The main class is compulsory. Set it to point your SpringBootApplication. - "Main-Class": "org.scf.azure.gradle.GradleDemoApplication" - ) - } -} - -repositories { - mavenLocal() - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter' - implementation "org.springframework.cloud:spring-cloud-function-adapter-azure:4.1.0-SNAPSHOT" -} - -tasks.named('test') { - useJUnitPlatform() -} - -// Configuration options: https://github.com/microsoft/azure-gradle-plugins/wiki/Configuration -azurefunctions { - resourceGroup = 'java-functions-group' - appName = 'scff-azure-gradle-sample' - region = 'westus' - appServicePlanName = 'java-functions-app-service-plan' - pricingTier = 'EP1' - runtime { - os = 'linux' - javaVersion = '11' - } - auth { - type = 'azure_cli' - } - appSettings { - FUNCTIONS_EXTENSION_VERSION = '~4' - } - localDebug = "transport=dt_socket,server=y,suspend=n,address=5005" -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index c1962a79e29d3e0ab67b14947c167a862655af9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62076 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 diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 37aef8d3f..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip -networkTimeout=10000 -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew deleted file mode 100755 index aeb74cbb4..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original 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. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew.bat b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew.bat deleted file mode 100644 index 6689b85be..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/host.json b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/host.json deleted file mode 100644 index 5d8f8a197..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/host.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[4.*, 5.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/settings.gradle b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/settings.gradle deleted file mode 100644 index 69c977517..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'gradle-demo' diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/java/org/scf/azure/gradle/GradleDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/java/org/scf/azure/gradle/GradleDemoApplication.java deleted file mode 100644 index 3d5902df8..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/java/org/scf/azure/gradle/GradleDemoApplication.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.scf.azure.gradle; - -import java.util.Optional; -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.adapter.azure.AzureFunctionUtil; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; - -@SpringBootApplication -public class GradleDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(GradleDemoApplication.class, args); - } - - /** - * Plain Spring bean (not Spring Cloud Functions!) - */ - @Autowired - private Function, String> uppercase; - - @FunctionName("bean") - public String plainBean( - @HttpTrigger(name = "req", methods = { HttpMethod.GET, - HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - // Inject the ExecutionContext as Message header - Message enhancedRequest = (Message) AzureFunctionUtil.enhanceInputIfNecessary( - request.getBody().get(), - context); - - return this.uppercase.apply(enhancedRequest); - } - - @Bean - public Function, String> uppercase() { - return message -> { - ExecutionContext context = (ExecutionContext) message.getHeaders().get(AzureFunctionUtil.EXECUTION_CONTEXT); - - String updatedPayload = message.getPayload().toUpperCase(); - - context.getLogger().info("Azure Test: " + updatedPayload); - - return message.getPayload().toUpperCase(); - }; - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/resources/application.properties deleted file mode 100644 index 1b45c68af..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.main.allow-circular-references=true \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/.gitignore b/spring-cloud-function-samples/function-sample-azure-http-trigger/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f17644411d6e840bd5a10c6ecda0175f18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7fcd..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/README.adoc b/spring-cloud-function-samples/function-sample-azure-http-trigger/README.adoc deleted file mode 100644 index d5cbed220..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/README.adoc +++ /dev/null @@ -1,94 +0,0 @@ -== Azure Functions HTTP triggers sample - -IMPORTANT: For a general information about building and deploying `Azure Functions` with Spring Cloud Function, consult the https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html[Azure Adapter] documentation. - -Azure Functions may be invoked via HTTP requests to build serverless APIs. -Find more about the https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook?tabs=in-process%2Cfunctionsv2&pivots=programming-language-java[HTTP triggers]. - -=== Usage - -==== Package Staging folder - -Use the script below to package your staging folder: - -[source,shell] ----- -./mvnw clean package ----- - -==== Run Azure Functions locally - -Use the script below to run the function locally. - -[source,shell] ----- -./mvnw azure-functions:run ----- - -NOTE: To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here]). - -NOTE: https://github.com/Azure/azure-functions-core-tools[Azure Functions Core Tools] version `4.0.5030` or newer is required! - -For some configuration you would need the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator[Azurite emulator] as well. - - -==== Deploy Azure Functions to Azure Cloud - -Make sure you are logged in your Azure account. - -[source,shell] ----- -az login ----- - -then build and deploy - -[source,shell] ----- -./mvnw clean package -./mvnw azure-functions:deploy ----- - - -==== Debug locally - -Run the function in debug mode. - -[source,shell] ----- -./mvnw azure-functions:run -DenableDebug ----- - -Alternatively and the `JAVA_OPTS` value to your `local.settings.json` like this: - -[source,json] ----- -{ - "IsEncrypted": false, - "Values": { - ... - "FUNCTIONS_WORKER_RUNTIME": "java", - "JAVA_OPTS": "-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005" - } -} ----- - - -For VSCode remote debug use configuration like this: - -[source,json] ----- -{ - "version": "0.2.0", - "configurations": [ - { - "type": "java", - "name": "Attach to Remote Program", - "request": "attach", - "hostName": "localhost", - "port": "5005" - }, - ... - ] -} ----- \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw b/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw deleted file mode 100755 index 8a8fb2282..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw.cmd b/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw.cmd deleted file mode 100644 index 1d8ab018e..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/mvnw.cmd +++ /dev/null @@ -1,188 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml b/spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml deleted file mode 100644 index 50fd06a98..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - com.example.azure.di - azure-httptrigger-demo - 0.0.1-SNAPSHOT - azure-httptrigger-demo - - Demo Spring Boot, Azure Function - HttpTrigger (DI adapter) - - - 17 - 1.0.28.RELEASE - - - com.example.azure.di.httptriggerdemo.HttpTriggerDemoApplication - - - 1.22.0 - spring-cloud-function-samples - westus - java-functions-group - java-functions-app-service-plan - EP1 - - - - - org.springframework.cloud - spring-cloud-function-adapter-azure - 4.1.0-SNAPSHOT - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - - ${functionAppName} - ${functionResourceGroup} - ${functionAppRegion} - ${functionAppServicePlanName} - ${functionPricingTier} - - ${project.basedir}/src/main/resources/host.json - - - linux - 17 - - - 7072 - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${spring-boot-thin-layout.version} - - - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/HttpTriggerDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/HttpTriggerDemoApplication.java deleted file mode 100644 index fc7bd8ea3..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/HttpTriggerDemoApplication.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.httptriggerdemo; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class HttpTriggerDemoApplication { - - @Bean - public Function echo() { - return payload -> payload; - } - - @Bean - public Function uppercase() { - return payload -> payload.toUpperCase(); - } - - @Bean - public Function reverse() { - return payload -> new StringBuilder(payload).reverse().toString(); - } - - public static void main(String[] args) { - SpringApplication.run(HttpTriggerDemoApplication.class, args); - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/MyAzureFunction.java b/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/MyAzureFunction.java deleted file mode 100644 index 6838aa7d7..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/java/com/example/azure/di/httptriggerdemo/MyAzureFunction.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.httptriggerdemo; - -import java.util.Optional; -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.stereotype.Component; - -@Component -public class MyAzureFunction { - - /** - * Plain Spring bean (not Spring Cloud Functions!) - */ - @Autowired - private Function echo; - - /** - * Plain Spring bean (not Spring Cloud Functions!) - */ - @Autowired - private Function uppercase; - - /** - * The FunctionCatalog leverages the Spring Cloud Function framework. - */ - @Autowired - private FunctionCatalog functionCatalog; - - @FunctionName("bean") - public String plainBeans( - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - return echo.andThen(uppercase).apply(request.getBody().get()); - } - - @FunctionName("scf") - public String springCloudFunction( - @HttpTrigger(name = "req", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - - // Use SCF composition. Composed functions are not just spring beans but SCF such. - Function composed = this.functionCatalog.lookup("echo|reverse|uppercase"); - - return (String) composed.apply(request.getBody().get()); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/host.json b/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/host.json deleted file mode 100644 index 10d0c0748..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/main/resources/host.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.*, 4.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/test/java/com/example/azure/di/httptriggerdemo/HttptriggerDemoApplicationTests.java b/spring-cloud-function-samples/function-sample-azure-http-trigger/src/test/java/com/example/azure/di/httptriggerdemo/HttptriggerDemoApplicationTests.java deleted file mode 100644 index dbc76d294..000000000 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/src/test/java/com/example/azure/di/httptriggerdemo/HttptriggerDemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.azure.di.httptriggerdemo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class HttptriggerDemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/.gitignore b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/.gitignore deleted file mode 100644 index 7ed0d6b67..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/README.md b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/README.md deleted file mode 100644 index 5b5fc311c..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Azure Function with Kafka Trigger & Output Binding - -Spring Cloud Function example for implementing an Azure functions with [KafkaTrigger](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-kafka-trigger?tabs=in-process%2Cconfluent&pivots=programming-language-java) and [Kafka Binding](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-kafka-output?tabs=in-process%2Cconfluent&pivots=programming-language-java) support. - -The Azure function is triggered by messages sent on the `trigger` topic and in turn calls the `uppercase` SCF with the trigger payload. The SCF capitalizes the input json value fields and sends the result to an output Kafka topic called: `output`. - -## Running Locally - -First start a Kafka server locally. -The `./src/main/resources/docker-compose-demo.yaml` helps to start locally Zookeeper, Kafka and Kafka UI. - -``` -docker-compose -f ./src/main/resources/docker-compose-demo.yaml up -``` -You can reach the Kafka UI (Redpanda) dashboard on http://localhost:8080/topics - -![](./src/main/doc/kafka-ui-topics.png) - -The docker-compose pre-creates the `trigger` and `output` topics used by the function. - -Next build and run the Azure function: - -``` -./mvnw clean package -./mvnw azure-functions:run -``` - -From the Kafka UI, got to the `trigger` topic view (http://localhost:8080/topics/trigger), select `Actions/Publish Message` and submit a new JSON message: -```json -{ "foo" : "bar"} -``` - -![](./src/main/doc/kafka-publish-message.png) - - -Push the `Publish` button and let the function do its job and check the `output` topic (http://localhost:8080/topics/output) : - -![](./src/main/doc/output-topic.png) - -e.g.the `bar` is in uppercase: - -```json -{ "foo" : "BAR"} -``` - - - -## Running on Azure (TODO: WIP) - -Make sure you are logged in your Azure account. -``` -az login -``` - -Build and deploy - -``` -./mvnw clean package -./mvnw azure-functions:deploy -``` - -## Implementation - -Configure the [Kafka extension](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-kafka?tabs=in-process%2Cportal&pivots=programming-language-java#hostjson-settings) in the `host.json` settings: - -```json -{ - "functionTimeout": "00:05:00", - "version": "2.0", - "extensions": { - "kafka": { - "maxBatchSize": 64, - "SubscriberIntervalInSeconds": 1, - "ExecutorChannelCapacity": 1, - "ChannelFullRetryIntervalInMs": 50 - } - }, - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.3.0, 4.0.0)" - } -} -``` - -Also to allow your functions to scale properly on the Premium plan when using Kafka triggers and bindings, you need to [enable runtime scale monitoring](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-kafka?tabs=in-process%2Cportal&pivots=programming-language-java#enable-runtime-scaling). - - -## Notes - -* Disable the `spring-boot-maven-plugin` in favor of the `azure-functions-maven-plugin`. -* Exclude the `org.springframework.boot:spring-boot-starter-logging` dependency from the `org.springframework.cloud:spring-cloud-function-adapter-azure`. -* In `local.settings.json` set the local values for the `%BrokerList`, `%ConfluentCloudUsername%` and the `%TriggerKafkaTopic%` trigger and binding variables: - -``` -{ - "IsEncrypted": false, - "Values": { -... - "BrokerList": "localhost:9092", - "ConfluentCloudUsername": "test", - "TriggerKafkaTopic": "trigger" - } -} -``` - -## References - -* [Apache Kafka for Confluent Cloud - Azure portal](https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create) - show how to create an instance of Apache Kafka for Confluent Cloud. -- [Create a Cluster in Confluent Cloud](https://docs.confluent.io/cloud/current/clusters/create-cluster.html#create-a-cluster-in-ccloud) \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw deleted file mode 100755 index 8a8fb2282..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw.cmd b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw.cmd deleted file mode 100644 index 1d8ab018e..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/mvnw.cmd +++ /dev/null @@ -1,188 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml deleted file mode 100644 index 304bc8c40..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - example.scf.azure - kafka-trigger-azure-spring-function - 0.0.1-SNAPSHOT - kafka-trigger-demo - Demo project for Spring Boot - - 17 - 4.1.0-SNAPSHOT - 1.0.28.RELEASE - - example.KafkaTriggerDemoApplication - - example-spring-function-resource-group - kafka-trigger-azure-spring-function - westeurope - ${project.build.directory}/azure-functions/${functionAppName} - java-functions-app-service-plan - 1.22.0 - - - - - org.springframework.cloud - spring-cloud-function-context - ${spring-cloud-function-dependencies.version} - - - org.springframework.cloud - spring-cloud-function-adapter-azure - ${spring-cloud-function-dependencies.version} - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - ${functionResourceGroup} - ${functionAppName} - ${functionAppRegion} - ${functionAppServicePlanName} - - ${project.basedir}/src/main/azure/host.json - ${project.basedir}/src/main/azure/local.settings.json - - - linux - 17 - - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - FUNCTIONS_WORKER_RUNTIME - java - - - - - - package-functions - - package - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${spring-boot-thin-layout.version} - - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/host.json b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/host.json deleted file mode 100644 index 8bb952206..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/host.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functionTimeout": "00:05:00", - "version": "2.0", - "extensions": { - "kafka": { - "maxBatchSize": 64, - "SubscriberIntervalInSeconds": 1, - "ExecutorChannelCapacity": 1, - "ChannelFullRetryIntervalInMs": 50 - } - }, - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.3.0, 4.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/local.settings.json b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/local.settings.json deleted file mode 100644 index 87b48b54b..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/azure/local.settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "AzureWebJobsDashboard": "", - "FUNCTIONS_WORKER_RUNTIME": "java", - - "BrokerList": "localhost:9092", - "ConfluentCloudUsername": "test", - "ConfluentCloudPassword": "test", - "TriggerKafkaTopic": "trigger" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-publish-message.png b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-publish-message.png deleted file mode 100644 index f8122d360d0eb3dcde9435f83d971084794f92ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43717 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 diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-ui-topics.png b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/kafka-ui-topics.png deleted file mode 100644 index 3d2fd4ac69dbf67ab8e71b20c4ed0dc5e78e1b3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64359 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

;0F8tKpb=oHa| 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 P0eHIn; diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/output-topic.png b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/doc/output-topic.png deleted file mode 100644 index 8aa11a41f3a26bb8721d2f72e4abbe9c46b7fe83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104524 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, String> uppercase(JsonMapper mapper) { - return message -> { - - // Convert the message payload into Azure's KafkaEntity format. - KafkaEntity kafkaEntity = mapper.fromJson(message.getPayload(), KafkaEntity.class); - - // Business logic: convert the JSON string values into uppercase. - if (kafkaEntity.getValue() != null) { - Map valueMap = mapper.fromJson(kafkaEntity.getValue(), Map.class); - if (valueMap != null) { - valueMap.forEach((k, v) -> valueMap.put(k, - v != null && v instanceof String ? ((String) v).toUpperCase() : null)); - return mapper.toString(valueMap); - } - } - - return mapper.toString(null); - }; - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/UppercaseHandler.java b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/UppercaseHandler.java deleted file mode 100644 index 2e7f33b11..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/UppercaseHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2022 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 java.util.function.Function; - -import com.microsoft.azure.functions.BrokerAuthenticationMode; -import com.microsoft.azure.functions.BrokerProtocol; -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.OutputBinding; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.KafkaOutput; -import com.microsoft.azure.functions.annotation.KafkaTrigger; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; - -@Component -public class UppercaseHandler { - - @Autowired - private Function, String> uppercase; - - @FunctionName("KafkaTrigger") - public void execute( - @KafkaTrigger( - name = "KafkaTrigger", - topic = "%TriggerKafkaTopic%", - brokerList = "%BrokerList%", - consumerGroup = "$Default", - username = "%ConfluentCloudUsername%", - password = "%ConfluentCloudPassword%", - authenticationMode = BrokerAuthenticationMode.PLAIN, - protocol = BrokerProtocol.PLAINTEXT, - // protocol = BrokerProtocol.SASLSSL, - // sslCaLocation = "confluent_cloud_cacert.pem", // Enable this line for windows. - dataType = "string") String kafkaEventData, - @KafkaOutput( - name = "kafkaOutput", - topic = "output", - brokerList="%BrokerList%", - username = "%ConfluentCloudUsername%", - password = "%ConfluentCloudPassword%", - authenticationMode = BrokerAuthenticationMode.PLAIN, - // sslCaLocation = "confluent_cloud_cacert.pem", // Enable this line for windows. - protocol = BrokerProtocol.PLAINTEXT - // protocol = BrokerProtocol.SASLSSL - ) OutputBinding output, - final ExecutionContext context) { - - context.getLogger().info(kafkaEventData); - - Message message = MessageBuilder.withPayload(kafkaEventData).build(); - - String response = uppercase.apply(message); - - output.setValue(response); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaEntity.java b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaEntity.java deleted file mode 100644 index af9be822b..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaEntity.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022 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.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class KafkaEntity { - @JsonProperty("Offset") - private int offset; - @JsonProperty("Partition") - private int partition; - @JsonProperty("Timestamp") - private String timestamp; - @JsonProperty("Topic") - private String topic; - @JsonProperty("Key") - private String key; - @JsonProperty("Value") - private String value; - @JsonProperty("Headers") - private KafkaHeaders[] headers; - - public int getOffset() { - return offset; - } - - public void setOffset(int offset) { - this.offset = offset; - } - - public int getPartition() { - return partition; - } - - public void setPartition(int partition) { - this.partition = partition; - } - - public String getTimestamp() { - return timestamp; - } - - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } - - public String getTopic() { - return topic; - } - - public void setTopic(String topic) { - this.topic = topic; - } - - public String getValue() { - return value; - } - - - public void setValue(String value) { - this.value = value; - } - - public KafkaHeaders[] getHeaders() { - return headers; - } - - public void setHeaders(KafkaHeaders[] headers) { - this.headers = headers; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaHeaders.java b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaHeaders.java deleted file mode 100644 index af26e25f7..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/entity/KafkaHeaders.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022 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.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class KafkaHeaders { - @JsonProperty("Key") - private String key; - @JsonProperty("Value") - private String value; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/resources/docker-compose-demo.yaml b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/resources/docker-compose-demo.yaml deleted file mode 100644 index c184f5a1d..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/resources/docker-compose-demo.yaml +++ /dev/null @@ -1,63 +0,0 @@ -version: '2.1' - -services: - zookeeper: - image: zookeeper:3.4.9 - hostname: zookeeper - ports: - - "2181:2181" - environment: - ZOO_MY_ID: 1 - ZOO_PORT: 2181 - ZOO_SERVERS: server.1=zookeeper:2888:3888 - # volumes: - # - ./zk-single-kafka-single/zookeeper/data:/data - # - ./zk-single-kafka-single/zookeeper/datalog:/datalog - - kafka1: - image: confluentinc/cp-kafka:7.2.2 - hostname: kafka1 - ports: - - "9092:9092" - environment: - KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://kafka1:19092,LISTENER_DOCKER_EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER_INTERNAL:PLAINTEXT,LISTENER_DOCKER_EXTERNAL:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER_INTERNAL - KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" - KAFKA_BROKER_ID: 1 - KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - # volumes: - # - ./zk-single-kafka-single/kafka1/data:/var/lib/kafka/data - depends_on: - - zookeeper - - - init-kafka: - image: confluentinc/cp-kafka:7.2.2 - depends_on: - - kafka1 - entrypoint: [ '/bin/sh', '-c' ] - command: | - " - # blocks until kafka is reachable - kafka-topics --bootstrap-server kafka1:19092 --list - - echo -e 'Creating kafka topics' - kafka-topics --bootstrap-server kafka1:19092 --create --if-not-exists --topic trigger --replication-factor 1 --partitions 1 - kafka-topics --bootstrap-server kafka1:19092 --create --if-not-exists --topic output --replication-factor 1 --partitions 1 - - echo -e 'Successfully created the following topics:' - kafka-topics --bootstrap-server kafka1:19092 --list - " - - kconsole: - image: docker.redpanda.com/vectorized/console:latest - restart: on-failure - hostname: kconsole - ports: - - "8080:8080" - environment: - KAFKA_BROKERS: "kafka1:19092" - depends_on: - - kafka1 \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f17644411d6e840bd5a10c6ecda0175f18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| diff --git a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7fcd..000000000 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/.gitignore b/spring-cloud-function-samples/function-sample-azure-time-trigger/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f17644411d6e840bd5a10c6ecda0175f18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58727 zcmb5W18`>1vNjyPv28mO+cqb*Z6_1kwr$(?#I}=(ZGUs`Jr}3`|DLbDUA3!L?dtC8 zUiH*ktDo+@6r@4HP=SCTA%WmZqm^Ro`Ls)bfPkcdfq?#g1(Fq27W^S8Cq^$TC?_c< zs-#ROD;6C)1wFuk7<3)nGuR^#!H;n&3*IjzXg+s8Z_S!!E0jUq(`}Itt=YdYa5Z_s z&e>2={87knpF*PKNzU;lsbk#P(l^WBvb$yEz)z+nYH43pKodrDkMp@h?;n{;K}hl>Fb^ zqx}C0|D7kg|Cj~3f7hn_zkAE}|6t|cZT|S5Hvb#3nc~C14u5UI{6#F<|FkJ0svs&S zA}S{=DXLT*BM1$`2rK%`D@vEw9l9%*=92X_2g?Fwfi=6Zfpr7+<~sgP#Bav+Df2ts zwtu~70zhqV?mrzM)}r7mMS`Hk_)NrI5K%CTtQtDxqw5iv5F0!ksIon{qqpPVnU?ds zN$|Vm{MHKEReUy>1kVfT-$3))Js0p2W_LFy3cjjZ7za0R zPdBH>y&pb0vr1|ckDpt2p$IQhwnPs5G*^b-y}sg4W!ALn}a`pY0JIa$H0$eV2T8WjWD= zWaENacQhlTyK4O!+aOXBurVR2k$eb8HVTCxy-bcHlZ4Xr!`juLAL#?t6|Ba!g9G4I zSwIt2Lla>C?C4wAZ8cKsZl9-Yd3kqE`%!5HlGdJJaFw0mu#--&**L-i|BcIdc3B$;0FC;FbE-dunVZ; zdIQ=tPKH4iJQQ=$5BeEMLov_Hn>gXib|9nOr}>eZt@B4W^m~>Zp#xhn1dax+?hS!AchWJ4makWZs@dQUeXQ zsI2+425_{X@t2KN zIbqec#)Jg5==VY3^YBeJ2B+%~^Y8|;F!mE8d(`UgNl2B9o>Ir5)qbBr)a?f%nrP zQyW(>FYPZjCVKDOU;Bw#PqPF1CCvp)dGdA&57a5hD&*vIc)jA)Z-!y5pS{5W6%#prH16zgD8s zexvpF#a|=*acp>L^lZ(PT)GiA8BJL-9!r8S$ZvXRKMVtiGe`+!@O%j<1!@msc177U zTDy>WOZu)W5anPrweQyjIu3IJC|ngdjZofGbdW&oj^DJlC7$;|xafB45evT|WBgGf-b|9y0J`fe0W-vw6xh}` z=(Tnq(-K0O{;VUcKe2y63{HXc+`R_#HLwnZ0rzWO*b#VeSuC4NG!H_ApCypbt1qx( z6y7Q$5(JOpQ&pTkc^0f}A0Kq*?;g9lEfzeE?5e2MBNZB)^8W1)YgdjsVyN+I9EZlh z3l}*}*)cFl=dOq|DvF=!ui$V%XhGQ%bDn3PK9 zV%{Y|VkAdt^d9~y4laGDqSwLd@pOnS&^@sI7}YTIb@El1&^_sq+{yAGf0|rq5TMp# z6d~;uAZ(fY3(eH=+rcbItl2=u6mf|P{lD4kiRCv;>GtFaHR3gim?WU9RjHmFZLm+m z+j<}_exaOQ1a}=K#voc~En+Mk_<(L!?1e#Uay~|H5q)LjD*yE6xFYQ-Wx{^iH1@pP zC0De#D6I26&W{;J40sZB!=%{c?XdO?YQvnTMA3TwfhAm@bvkX*(x?JTs*dFDv^=2X z284}AK)1nRn+8(Q2P?f)e>0~;NUI9%p%fnv1wBVpoXL+9OE`Vv1Y7=+nub$o7AN>y zB?R(^G8PYcMk4bxe7XItq@48QqWKb8fa*i9-N)=wdU-Q^=}!nFgTr_uT=Z=9pq z`{7!$U|+fnXFcsJ4GNm3JQQCN+G85k$)ZLhF{NbIy{REj84}Zt;0fe#>MARW)AoSb zrBpwF37ZVBMd>wZn_hAadI*xu8)Y#`aMbwRIA2n^-OS~M58_@j?#P1|PXJ1XBC9{4 zT^8*|xu<@(JlSOT*ILrVGr+7$nZN`Z3GxJJO@nY&mHsv^^duAh*lCu5q+S6zWA+`- z%^*y#)O7ko_RwGJl;bcEpP03FOrhlLWs`V_OUCrR-g>NJz*pN|itmN6O@Hw05Zq;Xtif%+sp4Py0{<7<^c zeoHHhRq>2EtYy9~2dZywm&OSk`u2ECWh6dJY?;fT-3-$U`!c(o$&hhPC%$~fT&bw3 zyj+8aXD;G!p*>BC6rpvx#6!|Qaic;KEv5>`Y+R(6F^1eIeYG6d1q3D3OL{7%7iw3R zwO)W7gMh27ASSB>-=OfP(YrKqBTNFv4hL@Im~~ombbSu44p~VoH$H-6+L_JW>Amkl zhDU~|r77?raaxD!-c$Ta?WAAi{w3T}YV=+S?1HQGC0+{Bny_^b+4Jum}oW4c=$ z#?D<}Ds{#d5v`L`${Pee;W84X*osNQ96xsKp^EAzuUh9#&zDX=eqdAp$UY)EGrkU% z(6m35n=46B$TNnejNSlih_!<)Iu@K!PW5S@Ya^0OK+EMWM=1w=GUKW^(r59U%i?d zzbo?|V4tDWGHHsrAQ}}ma#<`9r=M8%XF#%a=@Hn(p3wFBlkZ2L@8=*@J-^zuyF0aN zzJ7f!Jf8I+^6Tt$e+IIh zb80@?7y#Iz3w-0VEjgbHurqI>$qj<@n916)&O340!_5W9DtwR)P5mk6v2ljyK*DG5 zYjzE~m`>tq8HYXl%1JJ%e-%BqV4kRdPUZB1Cm$BQZr(fzp_@rn_W+;GwI$?L2Y4;b z)}c5D$#LT}2W8Si<`EHKIa_X+>+2PF(C*u~F=8E!jL(=IdQxY40%|( zoNg2Z&Aob@LEui-lJ#@)Ts)tE0_!*3{Uk)r{;-IZpX`N4mZX`#E|A;viQWImB6flI z?M_|xHCXV$5LOY-!U1_O1k;OWa=EchwlDCK4xHwBW2jE-6&%}og+9NILu${v10Z^Z#* zap|)B9a-AMU~>$r)3&|dQuP#MA$jnw54w*Ax~*_$iikp+j^OR8I5Fo<_UR#B-c>$? zeg)=;w^sGeAMi<3RGDRj$jA30Qq$e|zf2z;JyQ}tkU)ZI_k6tY%(`#AvL)p)iYXUy z5W9Su3NJ8mVyy)WqzFSk&vZM!;kUh8dVeA-myqcV%;xUne`PbHCPpvH?br`U2Y&dM zV!nJ!^n%`!H&!QSlpzLWnZpgi;#P0OAleH+<CfLa?&o|kyw1}W%6Pij zp$Vv5=;Z0LFN|j9i&9>zqX>*VnV3h#>n!2L?5gO6HJS3~kpy5G zYAVPMaB-FJOk3@OrxL(*-O~OB9^d{!G0K>wlzXuBm*$&%p1O#6SQ*?Q0CETLQ->XpfkW7< zj&Nep(}eAH1u$wWFvLV*lA{JOltP_%xKXC*a8DB&;{fD&2bATy>rC^kFY+$hFS7us;Y) zy_H?cv9XTHYz<4C<0b`WKC#{nJ15{F=oaq3x5}sYApT?Po+(Cmmo#dHZFO^{M#d~d znRT=TFATGVO%z_FNG-@G;9az|udZ>t@5l+A-K)BUWFn_|T#K3=d3EXRNqHyi#>;hX z*JQ`pT3#&tH>25laFlL6Rllu(seA*OboEd%rxMtz3@5v-+{qDP9&BcoS$2fgjgvp$ zc8!3=p0p@Ee1$u{Gg}Kkxg@M*qgZfYLlnD88{uwG1T?zxCbBR+x(RK$JB(eWJH#~; zZoY6L+esVRV?-*QmRCG}h`rB*Lv=uE%URF@+#l-g!Artx>Y9D;&G=jY2n2`J z{6-J%WX~Glx*QBmOOJ(RDRIzhfk&ibsm1t&&7aU{1P3U0uM%F2zJb4~50uby_ng+# zN)O9lK=dkJpxsUo7u8|e`Y~mmbxOTDn0i!i;d;ml#orN(Lc=j+n422NoSnlH6?0<0?th-qB7u}`5My%#?ES}>@RldOQz}WILz<$+cN~&ET zwUI01HCB((TyU$Ej8bxsE8oLmT-c7gA1Js?Iq`QMzIHV|)v)n2 zT_L(9x5%8*wU(C`VapaHoicWcm|0X@9TiNtbc|<4N6_H1F6&qgEEj=vjegFt;hC7- zLG7_=vedRFZ6Chbw!{#EpAlM?-sc#pc<~j#537n)M%RT)|L}y(ggi_-SLpsE3qi3V z=EEASxc>a{Su)jXcRS41Z@Mxk&0B7B<(?Izt5wpyyIBO|-M}ex8BhbIgi*X4 zDZ+Yk1<6&=PoZ=U-!9`!?sBVpYF#Y!JK<`fx}bXN651o0VVaW;t6ASVF@gq-mIDV_)?F^>rq1XX0NYy~(G=I6x%Fi5C2rMtvs z%P`g2>0{xLUy~#ye)%QAz^NkD5GUyPYl}K#;e-~UQ96`I$U0D!sMdQ>;%+c0h>k*Y z)sD1mi_@|rZnQ+zbWq~QxFlBQXj8WEY7NKaOYjUxAkGB8S#;l@b^C?;twRKl=mt0< zazifrBs`(q7_r14u1ZS`66VmsLpV>b5U!ktX>g4Nq~VPq6`%`3iCdr(>nS~uxxylU z>h(2p$XPJVh9BDpRLLzTDlNdp+oq8sOUlJ#{6boG`k)bwnsw5iy@#d{f_De-I|}vx6evw;ch97=;kLvM)-DBGwl6%fA%JItoMeyqjCR*_5Q70yd!KN zh=>ek8>f#~^6CJR0DXp0;7ifZjjSGBn}Cl{HeX!$iXMbtAU$F+;`%A<3TqbN#PCM& z&ueq$cB%pu2oMm_-@*aYzgn9`OiT@2ter*d+-$Aw42(@2Ng4mKG%M-IqX?q%3R|_( zN|&n$e1L#Ev=YMX5F53!O%))qDG3D(0rsOHblk;9ghWyqEOpg)mC$OduqpHAuIxr_>*|zy+|=EmOFn zFM+Ni%@CymLS-3vRWn=rVk?oZEz0V#y356IE6HR5#>7EigxZ05=cA|4<_tC8jyBJ| zgg!^kNwP7S^ooIj6riI9x`jFeQfRr4JCPumr<82M zto$j^Qb~MPmJ-|*2u{o7?yI8BI``zDaOCg2tG_5X;w<|uj5%oDthnLx-l4l)fmUGx z6N^jR|DC);yLi4q-ztTkf>*U$@2^w5(lhxu=OC|=WuTTp^!?2Nn27R`2FY_ zLHY-zFS}r+4|XyZw9b0D3)DmS!Gr+-LSdI}m{@-gL%^8CFSIYL?UZaCVd)2VI3|ay zwue39zshVrB+s2lp*};!gm<79@0HkjhgF^>`UhoR9Mi`aI#V#fI@x&1K3f&^8kaq% zkHVg$CTBoaGqEjrL)k*Y!rtiD2iQLYZ%|B}oBl8GHvR%n>HiIQN*+$mCN>I=c7H2N z&K4$4e@E^ff-cVHCbrHNMh4Dy|2Q;M{{xu|DYjeaRh2FK5QK!bG_K`kbBk$l$S4UF zq?F-%7UrX_Q?9M)a#WvcZ^R-fzJB5IFP>3uEoeCAAhN5W-ELRB&zsCnWY6#E?!)E56Pe+bxHjGF6;R9Hps)+t092-bf4 z_Wieg+0u5JL++k)#i0r?l`9*k)3ZlHOeMJ1DTdx9E1J2@BtdD3qX;&S_wMExOGv$T zl^T%oxb+)vq6vJvR`8{+YOsc@8}wSXpoK%v0k@8X*04Se3<8f)rE|fRXAoT!$6MdrKSuzeK@L*yug?MQs8oTbofqW)Df# zC2J3irHAaX_e~SGlBoRhEW`W6Z}&YX|5IMfzskAt{B*m z*w=3i!;x5Gfgc~>y9fPXFAPMhO@Si}SQESjh`P|dlV5HPRo7j(hV=$o8UMIT7~7+k z*@Sd>f%#{ARweJYhQs~ECpHie!~YXL|FJA;KS4m|CKFnT{fN`Ws>N?CcV@(>7WMPYN} z1}Wg+XU2(Yjpq7PJ|aSn;THEZ{4s8*@N!dz&bjys_Zk7%HiD+56;cF26`-a zEIo!B(T|L*uMXUvqJs&54`^@sUMtH-i~rOM9%$xGXTpmow$DxI>E5!csP zAHe|);0w%`I<==_Zw9t$e}?R+lIu%|`coRum(1p~*+20mBc?Z=$+z<0n&qS0-}|L4 zrgq|(U*eB%l3nfC=U1Y?(Tf@0x8bhdtsU2w&Y-WvyzkiyJ>GZqUP6c+<_p0`ZOnIK z#a~ynuzRWxO6c;S@*}B1pTjLJQHi(+EuE2;gG*p^Fq%6UoE1x95(^BY$H$$soSf=vpJ)_3E zp&$l=SiNaeoNLAK8x%XaHp3-So@F7 z3NMRRa@%k+Z$a%yb25ud&>Cdcb<+}n>=jZ`91)a z{wcA(j$%z#RoyB|&Z+B4%7Pe*No`pAX0Y;Ju4$wvJE{VF*Qej8C}uVF=xFpG^rY6Y+9mcz$T9^x(VP3uY>G3Zt&eU{pF*Bu<4j9MPbi4NMC=Z$kS6DMW9yN#vhM&1gd1t}8m(*YY9 zh2@s)$1p4yYT`~lYmU>>wKu+DhlnI1#Xn4(Rnv_qidPQHW=w3ZU!w3(@jO*f;4;h? zMH0!08(4=lT}#QA=eR(ZtW1=~llQij7)L6n#?5iY_p>|_mLalXYRH!x#Y?KHyzPB^ z6P3YRD}{ou%9T%|nOpP_??P;Rmra7$Q*Jz-f?42PF_y>d)+0Q^)o5h8@7S=je}xG# z2_?AdFP^t{IZHWK)9+EE_aPtTBahhUcWIQ7Awz?NK)ck2n-a$gplnd4OKbJ;;tvIu zH4vAexlK2f22gTALq5PZ&vfFqqERVT{G_d`X)eGI%+?5k6lRiHoo*Vc?ie6dx75_t z6hmd#0?OB9*OKD7A~P$e-TTv3^aCdZys6@`vq%Vi_D8>=`t&q9`Jn1=M#ktSC>SO3 z1V?vuIlQs6+{aHDHL?BB&3baSv;y#07}(xll9vs9K_vs2f9gC9Biy+9DxS77=)c z6dMbuokO-L*Te5JUSO$MmhIuFJRGR&9cDf)@y5OQu&Q$h@SW-yU&XQd9;_x;l z<`{S&Hnl!5U@%I~5p)BZspK894y7kVQE7&?t7Z|OOlnrCkvEf7$J5dR?0;Jt6oANc zMnb_Xjky|2ID#fhIB2hs-48Er>*M?56YFnjC)ixiCes%fgT?C|1tQupZ0Jon>yr|j z6M66rC(=;vw^orAMk!I1z|k}1Ox9qOILGJFxU*ZrMSfCe?)wByP=U73z+@Pfbcndc=VzYvSUnUy z+-B+_n`=f>kS8QBPwk+aD()=#IqkdxHPQMJ93{JGhP=48oRkmJyQ@i$pk(L&(p6<0 zC9ZEdO*i+t`;%(Ctae(SjV<@i%r5aune9)T4{hdzv33Uo9*K=V18S$6VVm^wgEteF za0zCLO(9~!U9_z@Qrh&rS|L0xG}RWoE1jXiEsrTgIF4qf#{0rl zE}|NGrvYLMtoORV&FWaFadDNCjMt|U8ba8|z&3tvd)s7KQ!Od*Kqe(48&C7=V;?`SQV)Qc?6L^k_vNUPbJ>>!5J?sDYm5kR&h_RZk)MfZ1 znOpQ|T;Me(%mdBJR$sbEmp3!HKDDSmMDnVpeo{S13l#9e6OImR$UPzjd-eCwmMwyT zm5~g6DIbY<_!8;xEUHdT(r_OQ<6QCE9Jy|QLoS>d(B zW6GRzX)~&Mx}})ITysFzl5_6JM*~ciBfVP(WF_r zY>z4gw&AxB%UV3Y{Y6z*t*o!p@~#u3X_t{Q9Us8ar8_9?N% zN&M~6y%2R(mAZ~@Tg1Oapt?vDr&fHuJ=V$wXstq|)eIG_4lB#@eU>fniJh zwJY<8yH5(+SSQ=$Y=-$2f$@^Ak#~kaR^NYFsi{XGlFCvK(eu{S$J(owIv17|p-%0O zL-@NyUg!rx0$Uh~JIeMX6JJE>*t<7vS9ev#^{AGyc;uio_-Je1?u#mA8+JVczhA2( zhD!koe;9$`Qgaxlcly4rdQ1VlmEHUhHe9TwduB+hm3wH2o27edh?|vrY{=;1Doy4& zIhP)IDd91@{`QQqVya(ASth4}6OY z-9BQj2d-%+-N7jO8!$QPq%o$9Fy8ja{4WT$gRP+b=Q1I48g-g|iLNjbhYtoNiR*d- z{sB}~8j*6*C3eM8JQj5Jn?mD#Gd*CrVEIDicLJ-4gBqUwLA-bp58UXko;M|ql+i5` zym-&U5BIS9@iPg#fFbuXCHrprSQKRU0#@yd%qrX1hhs*85R}~hahfFDq=e@bX))mf zWH%mXxMx|h5YhrTy;P_Xi_IDH*m6TYv>|hPX*_-XTW0G9iu!PqonQneKKaCVvvF^% zgBMDpN7!N?|G5t`v{neLaCFB{OyIl>qJQ_^0MJXQ zY2%-si~ej?F^%ytIIHU(pqT+3d+|IQ{ss#!c91R{2l*00e3ry!ha|XIsR%!q=E^Fal`6Oxu`K0fmPM?P6ZgzH7|TVQhl;l2 z)2w0L9CsN-(adU5YsuUw19OY_X69-!=7MIJ^(rUNr@#9l6aB8isAL^M{n2oD0FAHk97;X* z-INjZ5li`a|NYNt9gL2WbKT!`?%?lB^)J)9|025nBcBtEmWBRXQwi21EGg8>!tU>6Wf}S3p!>7vHNFSQR zgC>pb^&OHhRQD~7Q|gh5lV)F6i++k4Hp_F2L2WrcxH&@wK}QgVDg+y~o0gZ=$j&^W zz1aP8*cvnEJ#ffCK!Kz{K>yYW`@fc8ByF9X4XmyIv+h!?4&$YKl*~`ToalM{=Z_#^ zUs<1Do+PA*XaH;&0GW^tDjrctWKPmCF-qo7jGL)MK=XP*vt@O4wN1Y!8o`{DN|Rh) znK?nvyU&`ATc@U*l}=@+D*@l^gYOj&6SE|$n{UvyPwaiRQ_ua2?{Vfa|E~uqV$BhH z^QNqA*9F@*1dA`FLbnq;=+9KC@9Mel*>6i_@oVab95LHpTE)*t@BS>}tZ#9A^X7nP z3mIo+6TpvS$peMe@&=g5EQF9Mi9*W@Q`sYs=% z`J{3llzn$q;2G1{N!-#oTfQDY`8>C|n=Fu=iTk443Ld>>^fIr4-!R3U5_^ftd>VU> zij_ix{`V$I#k6!Oy2-z#QFSZkEPrXWsYyFURAo`Kl$LkN>@A?_);LE0rZIkmjb6T$ zvhc#L-Cv^4Ex*AIo=KQn!)A4;7K`pu-E+atrm@Cpmpl3e>)t(yo4gGOX18pL#xceU zbVB`#5_@(k{4LAygT1m#@(7*7f5zqB)HWH#TCrVLd9}j6Q>?p7HX{avFSb?Msb>Jg z9Q9DChze~0Psl!h0E6mcWh?ky! z$p#@LxUe(TR5sW2tMb#pS1ng@>w3o|r~-o4m&00p$wiWQ5Sh-vx2cv5nemM~Fl1Pn z@3ALEM#_3h4-XQ&z$#6X&r~U-&ge+HK6$)-`hqPj0tb|+kaKy*LS5@a9aSk!=WAEB z7cI`gaUSauMkEbg?nl0$44TYIwTngwzvUu0v0_OhpV;%$5Qgg&)WZm^FN=PNstTzW z5<}$*L;zrw>a$bG5r`q?DRc%V$RwwnGIe?m&(9mClc}9i#aHUKPLdt96(pMxt5u`F zsVoku+IC|TC;_C5rEU!}Gu*`2zKnDQ`WtOc3i#v}_9p>fW{L4(`pY;?uq z$`&LvOMMbLsPDYP*x|AVrmCRaI$UB?QoO(7mlBcHC};gA=!meK)IsI~PL0y1&{Dfm6! zxIajDc1$a0s>QG%WID%>A#`iA+J8HaAGsH z+1JH=+eX5F(AjmZGk|`7}Gpl#jvD6_Z!&{*kn@WkECV-~Ja@tmSR|e_L@9?N9 z3hyyry*D0!XyQh_V=8-SnJco#P{XBd1+7<5S3FA)2dFlkJY!1OO&M7z9uO?$#hp8K z><}uQS-^-B;u7Z^QD!7#V;QFmx0m%{^xtl3ZvPyZdi;^O&c;sNC4CHxzvvOB8&uHl zBN;-lu+P=jNn`2k$=vE0JzL{v67psMe_cb$LsmVfxA?yG z^q7lR00E@Ud3)mBPnT0KM~pwzZiBREupva^PE3~e zBgQ9oh@kcTk2)px3Hv^VzTtMzCG?*X(TDZ1MJ6zx{v- z;$oo46L#QNjk*1przHSQn~Ba#>3BG8`L)xla=P{Ql8aZ!A^Z6rPv%&@SnTI7FhdzT z-x7FR0{9HZg8Bd(puRlmXB(tB?&pxM&<=cA-;RT5}8rI%~CSUsR^{Dr%I2WAQghoqE5 zeQ874(T`vBC+r2Mi(w`h|d zA4x%EfH35I?h933@ic#u`b+%b+T?h=<}m@x_~!>o35p|cvIkkw07W=Ny7YcgssA_^ z|KJQrnu||Nu9@b|xC#C5?8Pin=q|UB?`CTw&AW0b)lKxZVYrBw+whPwZJCl}G&w9r zr7qsqm>f2u_6F@FhZU0%1Ioc3X7bMP%by_Z?hds`Q+&3P9-_AX+3CZ=@n!y7udAV2 zp{GT6;VL4-#t0l_h~?J^;trk1kxNAn8jdoaqgM2+mL&?tVy{I)e`HT9#Tr}HKnAfO zAJZ82j0+49)E0+=x%#1_D;sKu#W>~5HZV6AnZfC`v#unnm=hLTtGWz+21|p)uV+0= zDOyrLYI2^g8m3wtm-=pf^6N4ebLJbV%x`J8yd1!3Avqgg6|ar z=EM0KdG6a2L4YK~_kgr6w5OA;dvw0WPFhMF7`I5vD}#giMbMzRotEs&-q z^ji&t1A?l%UJezWv?>ijh|$1^UCJYXJwLX#IH}_1K@sAR!*q@j(({4#DfT|nj}p7M zFBU=FwOSI=xng>2lYo5*J9K3yZPwv(=7kbl8Xv0biOba>vik>6!sfwnH(pglq1mD-GrQi8H*AmfY*J7&;hny2F zupR}4@kzq+K*BE%5$iX5nQzayWTCLJ^xTam-EEIH-L2;huPSy;32KLb>>4 z#l$W^Sx7Q5j+Sy*E;1eSQQuHHWOT;1#LjoYpL!-{7W3SP4*MXf z<~>V7^&sY|9XSw`B<^9fTGQLPEtj=;<#x^=;O9f2{oR+{Ef^oZ z@N>P$>mypv%_#=lBSIr_5sn zBF-F_WgYS81vyW6$M;D_PoE&%OkNV1&-q+qgg~`A7s}>S`}cn#E$2m z%aeUXwNA(^3tP=;y5%pk#5Yz&H#AD`Jph-xjvZm_3KZ|J>_NR@croB^RUT~K;Exu5%wC}1D4nov3+@b8 zKyU5jYuQ*ZpTK23xXzpN51kB+r*ktnQJ7kee-gP+Ij0J_#rFTS4Gux;pkVB;n(c=6 zMks#)ZuXUcnN>UKDJ-IP-u2de1-AKdHxRZDUGkp)0Q#U$EPKlSLQSlnq)OsCour)+ zIXh@3d!ImInH7VrmR>p8p4%n;Tf6l2jx1qjJu>e3kf5aTzU)&910nXa-g0xn$tFa& z2qZ7UAl*@5o=PAh`6L${6S-0?pe3thPB4pahffb$#nL8ncN(Nyos`}r{%{g64Ji^= zK8BIywT0-g4VrhTt}n~Y;3?FGL74h?EG*QfQy0A8u>BtXuI{C-BYu*$o^}U1)z;8d zVN(ssw?oCbebREPD~I$-t7}`_5{{<0d10So7Pc2%EREdpMWIJI&$|rq<0!LL+BQM4 zn7)cq=qy|8YzdO(?NOsVRk{rW)@e7g^S~r^SCawzq3kj#u(5@C!PKCK0cCy zT@Tey2IeDYafA2~1{gyvaIT^a-Yo9kx!W#P-k6DfasKEgFji`hkzrmJ#JU^Yb%Nc~ zc)+cIfTBA#N0moyxZ~K!`^<>*Nzv-cjOKR(kUa4AkAG#vtWpaD=!Ku&;(D#(>$&~B zI?V}e8@p%s(G|8L+B)&xE<({g^M`#TwqdB=+oP|5pF3Z8u>VA!=w6k)zc6w2=?Q2` zYCjX|)fRKI1gNj{-8ymwDOI5Mx8oNp2JJHG3dGJGg!vK>$ji?n>5qG)`6lEfc&0uV z)te%G&Q1rN;+7EPr-n8LpNz6C6N0*v{_iIbta7OTukSY zt5r@sO!)rjh0aAmShx zd3=DJ3c(pJXGXzIh?#RR_*krI1q)H$FJ#dwIvz);mn;w6Rlw+>LEq4CN6pP4AI;!Y zk-sQ?O=i1Mp5lZX3yka>p+XCraM+a!1)`F`h^cG>0)f0OApGe(^cz-WoOno-Y(EeB zVBy3=Yj}ak7OBj~V259{&B`~tbJCxeVy@OEE|ke4O2=TwIvf-=;Xt_l)y`wuQ-9#D z(xD-!k+2KQzr`l$7dLvWf*$c8=#(`40h6d$m6%!SB1JzK+tYQihGQEwR*-!cM>#LD>x_J*w(LZbcvHW@LTjM?RSN z0@Z*4$Bw~Ki3W|JRI-r3aMSepJNv;mo|5yDfqNLHQ55&A>H5>_V9<_R!Ip`7^ylX=D<5 zr40z>BKiC@4{wSUswebDlvprK4SK2!)w4KkfX~jY9!W|xUKGTVn}g@0fG94sSJGV- z9@a~d2gf5s>8XT@`If?Oway5SNZS!L5=jpB8mceuf2Nd%aK2Zt|2FVcg8~7O{VPgI z#?H*_Kl!9!B}MrK1=O!Aw&faUBluA0v#gWVlAmZt;QN7KC<$;;%p`lmn@d(yu9scs zVjomrund9+p!|LWCOoZ`ur5QXPFJtfr_b5%&Ajig2dI6}s&Fy~t^j}()~4WEpAPL= zTj^d;OoZTUf?weuf2m?|R-7 z*C4M6ZhWF(F@2}nsp85rOqt+!+uZz3$ReX#{MP5-r6b`ztXDWl$_mcjFn*{sEx7f*O(ck+ou8_?~a_2Ztsq6qB|SPw26k!tLk{Q~Rz z$(8F1B;zK-#>AmmDC7;;_!;g&CU7a?qiIT=6Ts0cbUNMT6yPRH9~g zS%x{(kxYd=D&GKCkx;N21sU;OI8@4vLg2}L>Lb{Qv`B*O0*j>yJd#`R5ypf^lp<7V zCc|+>fYgvG`ROo>HK+FAqlDm81MS>&?n2E-(;N7}oF>3T9}4^PhY=Gm`9i(DPpuS- zq)>2qz!TmZ6q8;&M?@B;p1uG6RM_Y8zyId{-~XQD_}bXL{Jp7w`)~IR{l5a2?7!Vg zp!OfP4E$Ty_-K3VY!wdGj%2RL%QPHTL)uKfO5Am5<$`5 zHCBtvI~7q-ochU`=NJF*pPx@^IhAk&ZEA>w$%oPGc-}6~ywV~3-0{>*sb=|ruD{y$ ze%@-m`u28vKDaf*_rmN`tzQT>&2ltg-lofR8~c;p;E@`zK!1lkgi?JR0 z+<61+rEupp7F=mB=Ch?HwEjuQm}1KOh=o@ zMbI}0J>5}!koi&v9?!B?4FJR88jvyXR_v{YDm}C)lp@2G2{a{~6V5CwSrp6vHQsfb-U<{SSrQ zhjRbS;qlDTA&TQ2#?M(4xsRXFZ^;3A+_yLw>o-9GJ5sgsauB`LnB-hGo9sJ~tJ`Q>=X7sVmg<=Fcv=JDe*DjP-SK-0mJ7)>I zaLDLOU*I}4@cro&?@C`hH3tiXmN`!(&>@S2bFyAvI&axlSgd=!4IOi#+W;sS>lQ28 zd}q&dew9=x;5l0kK@1y9JgKWMv9!I`*C;((P>8C@JJRGwP5EL;JAPHi5fI|4MqlLU z^4D!~w+OIklt7dx3^!m6Be{Lp55j{5gSGgJz=hlNd@tt_I>UG(GP5s^O{jFU;m~l0 zfd`QdE~0Ym=6+XN*P`i0ogbgAJVjD9#%eBYJGIbDZ4s(f-KRE_>8D1Dv*kgO1~NSn zigx8f+VcA_xS)V-O^qrs&N9(}L!_3HAcegFfzVAntKxmhgOtsb4k6qHOpGWq6Q0RS zZO=EomYL%;nKgmFqxD<68tSGFOEM^u0M(;;2m1#4GvSsz2$jawEJDNWrrCrbO<}g~ zkM6516erswSi_yWuyR}}+h!VY?-F!&Y5Z!Z`tkJz&`8AyQ=-mEXxkQ%abc`V1s>DE zLXd7!Q6C)`7#dmZ4Lm?>CTlyTOslb(wZbi|6|Pl5fFq3y^VIzE4DALm=q$pK>-WM> z@ETsJj5=7=*4 z#Q8(b#+V=~6Gxl?$xq|?@_yQJ2+hAYmuTj0F76c(B8K%;DPhGGWr)cY>SQS>s7%O- zr6Ml8h`}klA=1&wvbFMqk}6fml`4A%G=o@K@8LHifs$)}wD?ix~Id@9-`;?+I7 zOhQN(D)j=^%EHN16(Z3@mMRM5=V)_z(6y^1b?@Bn6m>LUW7}?nupv*6MUVPSjf!Ym zMPo5YoD~t(`-c9w)tV%RX*mYjAn;5MIsD?0L&NQ#IY`9k5}Fr#5{CeTr)O|C2fRhY z4zq(ltHY2X)P*f?yM#RY75m8c<%{Y?5feq6xvdMWrNuqnR%(o(uo8i|36NaN<#FnT ze-_O*q0DXqR>^*1sAnsz$Ueqe5*AD@Htx?pWR*RP=0#!NjnaE-Gq3oUM~Kc9MO+o6 z7qc6wsBxp7GXx+hwEunnebz!|CX&`z{>loyCFSF-zg za}zec;B1H7rhGMDfn+t9n*wt|C_0-MM~XO*wx7-`@9~-%t?IegrHM(6oVSG^u?q`T zO<+YuVbO2fonR-MCa6@aND4dBy^~awRZcp!&=v+#kH@4jYvxt=)zsHV0;47XjlvDC8M1hSV zm!GB(KGLwSd{F-?dmMAe%W0oxkgDv8ivbs__S{*1U}yQ=tsqHJYI9)jduSKr<63$> zp;a-B^6Hg3OLUPi1UwHnptVSH=_Km$SXrCM2w8P z%F#Boi&CcZ5vAGjR1axw&YNh~Q%)VDYUDZ6f^0;>W7_sZr&QvRWc2v~p^PqkA%m=S zCwFUg2bNM(DaY>=TLmOLaDW&uH;Za?8BAwQo4+Xy4KXX;Z}@D5+}m)U#o?3UF}+(@jr$M4ja*`Y9gy~Y`0 z6Aex1*3ng@2er)@{%E9a3A;cts9cAor=RWt7ege)z=$O3$d5CX&hORZ3htL>jj5qT zW#KGQ;AZ|YbS0fvG~Y)CvVwXnBLJkSps7d~v;cj$D3w=rB9Tx>a&4>(x00yz!o*SOd*M!yIwx;NgqW?(ysFv8XLxs6Lrh8-F`3FO$}V{Avztc4qmZ zoz&YQR`*wWy_^&k-ifJ&N8Qh=E-fH6e}-}0C{h~hYS6L^lP>=pLOmjN-z4eQL27!6 zIe2E}knE;dxIJ_!>Mt|vXj%uGY=I^8(q<4zJy~Q@_^p@JUNiGPr!oUHfL~dw9t7C4I9$7RnG5p9wBpdw^)PtGwLmaQM=KYe z;Dfw@%nquH^nOI6gjP+K@B~0g1+WROmv1sk1tV@SUr>YvK7mxV3$HR4WeQ2&Y-{q~ z4PAR&mPOEsTbo~mRwg&EJE2Dj?TOZPO_@Z|HZX9-6NA!%Pb3h;G3F5J+30BoT8-PU z_kbx`I>&nWEMtfv(-m>LzC}s6q%VdBUVI_GUv3@^6SMkEBeVjWplD5y58LyJhikp4VLHhyf?n%gk0PBr(PZ3 z+V`qF971_d@rCO8p#7*#L0^v$DH>-qB!gy@ut`3 zy3cQ8*t@@{V7F*ti(u{G4i55*xY9Erw3{JZ8T4QPjo5b{n=&z4P^}wxA;x85^fwmD z6mEq9o;kx<5VneT_c-VUqa|zLe+BFgskp_;A)b>&EDmmP7Gx#nU-T@;O+(&&n7ljK zqK7&yV!`FIJAI+SaA6y=-H=tT`zWvBlaed!3X^_Lucc%Q=kuiG%65@@6IeG}e@`ieesOL} zKHBJBso6u&7gzlrpB%_yy<>TFwDI>}Ec|Gieb4=0fGwY|3YGW2Dq46=a1 zVo`Vi%yz+L9)9hbb%FLTC@-G(lODgJ(f&WmSCK9zV3-IV7XI<{2j}ms_Vmb!os)06 zhVIZPZF)hW--kWTCyDVRd2T&t|P&aDrtO5kzXy<*A+5$k7$>4+y%;% znYN-t#1^#}Z6d+ahj*Gzor+@kBD7@f|IGNR$4U=Y0J2#D2)YSxUCtiC1weJg zLp0Q&JFrt|In8!~1?fY0?=fPyaqPy$iQXJDhHP>N%B42Yck`Qz-OM_~GMuWow)>=Q z0pCCC7d0Z^Ipx29`}P3;?b{dO?7z0e{L|O*Z}nxi>X|RL8XAw$1eOLKd5j@f{RQ~Y zG?7$`hy@s7IoRF2@KA%2ZM6{ru9T5Gj)iDCz};VvlG$WuT+>_wCTS~J6`I9D{nsrU z2;X#OyopBgo778Q>D%_E>rMN~Po~d5H<`8|Zcv}F`xL5~NCVLX4Wkg007HhMgj9Pa z94$km3A+F&LzOJlpeFR*j+Y%M!Qm42ziH~cKM&3b;15s)ycD@3_tL-dk{+xP@J7#o z-)bYa-gd2esfy<&-nrj>1{1^_L>j&(MA1#WNPg3UD?reL*}V{ag{b!uT755x>mfbZ z0PzwF+kx91`qqOn`1>xw@801XAJlH>{`~|pyi6J;3s=cTOfelA&K5HX#gBp6s<|r5 zjSSj+CU*-TulqlnlP`}?)JkJ_7fg){;bRlXf+&^e8CWwFqGY@SZ=%NmLCXpYb+}7* z$4k}%iFUi^kBdeJg^kHt)f~<;Ovlz!9frq20cIj>2eIcG(dh57ry;^E^2T)E_8#;_9iJT>4sdCB_db|zO?Z^*lBN zNCs~f+Jkx%EUgkN2-xFF?B%TMr4#)%wq?-~+Nh;g9=n3tM>i5ZcH&nkVcPXgYRjG@ zf(Y7WN@hGV7o0bjx_2@bthJ`hjXXpfaes_(lWIw!(QK_nkyqj?{j#uFKpNVpV@h?7_WC3~&%)xHR1kKo`Cypj15#%0m z-o0GXem63g^|IltM?eZV=b+Z2e8&Z1%{0;*zmFc62mNqLTy$Y_c|9HiH0l>K z+mAx7DVYoHhXfdCE8Bs@j=t0f*uM++Idd25BgIm`Ad;I_{$mO?W%=JF82blr8rl>yMk6?pM z^tMluJ-ckG_}OkxP91t2o>CQ_O8^VZn$s$M_APWIXBGBq0Lt^YrTD5(Vwe2ta4y#DEYa(W~=eLOy7rD^%Vd$kL27M)MSpwgoP3P{ z!yS$zc|uP{yzaIqCwE!AfYNS;KW|OdP1Q%!LZviA0e^WDsIS5#= z!B{TW)VB)VHg{LoS#W7i6W>*sFz!qr^YS0t2kh90y=Je5{p>8)~D@dLS@QM(F# zIp{6M*#(@?tsu1Rq-Mdq+eV}ibRSpv#976C_5xlI`$#1tN`sK1?)5M+sj=OXG6dNu zV1K{y>!i0&9w8O{a>`IA#mo(3a zf*+Q=&HW7&(nX8~C1tiHZj%>;asBEp$p_Q!@Y0T8R~OuPEy3Lq@^t$8=~(FhPVmJJ z#VF8`(fNzK-b%Iin7|cxWP0xr*M&zoz|fCx@=Y!-0j_~cuxsDHHpmSo)qOalZ$bRl z2F$j0k3llJ$>28HH3l_W(KjF^!@LwtLej_b9;i;{ku2x+&WA@jKTO0ad71@_Yta!{ z2oqhO4zaU433LK371>E{bZ?+3kLZ9WQ2+3PTZAP90%P13Yy3lr3mhmy|>eN6(SHs1C%Q39p)YsUr7(kuaoIJGJhXV-PyG zjnxhcAC;fqY@6;MWWBnRK6ocG`%T&0&*k95#yK7DFtZV?;cy;!RD_*YJjsb6Q`$;K zy)&X{P`*5xEgjTQ9r=oh0|>Z_yeFm?ev!p z7q;JA4mtu@qa39v%6i)Z4%qwdxcHuOMO;a1wFMP_290FqH1OsmCG{ zq^afYrz2BQyQ0*JGE}1h!W9fKgk$b!)|!%q(1x?5=}PpmZQ$e;2EB*k4%+&+u;(E* z2n@=9HsqMv;4>Nn^2v&@4T-YTkd`TdWU^U*;sA5|r7TjZGnLY*xC=_K-GmDfkWEGC z;oN&!c1xB-<4J7=9 zJ(BedZwZhG4|64<=wvCn4)}w%Zx_TEs6ehmjVG&p5pi46r zg=3-3Q~;v55KR&8CfG;`Lv6NsXB}RqPVyNeKAfj9=Ol>fQlEUl2cH7=mPV!68+;jgtKvo5F#8&9m? z``w+#S5UR=QHFGM~noocC zVFa#v2%oo{%;wi~_~R2ci}`=B|0@ zinDfNxV3%iHIS(7{h_WEXqu!v~`CMH+7^SkvLe_3i}=pyDRah zN#L)F-`JLj6BiG}sj*WBmrdZuVVEo86Z<6VB}s)T$ZcWvG?i0cqI}WhUq2Y#{f~x# zi1LjxSZCwiKX}*ETGVzZ157=jydo*xC^}mJ<+)!DDCd4sx?VM%Y;&CTpw5;M*ihZ| zJ!FBJj0&j&-oJs?9a_I$;jzd%7|pdsQ3m`bPBe$nLoV1!YV8?Pw~0D zmSD-5Ue60>L$Rw;yk{_2d~v@CnvZa%!7{{7lb$kxWx!pzyh;6G~RbN5+|mFTbxcxf!XyfbLI^zMQSb6P~xzESXmV{9 zCMp)baZSz%)j&JWkc|Gq;_*$K@zQ%tH^91X2|Byv>=SmWR$7-shf|_^>Ll;*9+c(e z{N%43;&e8}_QGW+zE0m0myb-@QU%=Qo>``5UzB(lH0sK=E``{ZBl2Ni^-QtDp0ME1 zK88E-db_XBZQaU}cuvkCgH7crju~9eE-Y`os~0P-J=s;aS#wil$HGdK;Ut?dSO71ssyrdm{QRpMAV2nXslvlIE#+Oh>l7y_~?;}F!;ENCR zO+IG#NWIRI`FLntsz^FldCkky2f!d-%Pij9iLKr>IfCK);=}}?(NL%#4PfE(4kPQN zSC%BpZJ*P+PO5mHw0Wd%!zJsn&4g<$n#_?(=)JnoR2DK(mCPHp6e6VdV>?E5KCUF@ zf7W9wm%G#Wfm*NxTWIcJX-qtR=~NFxz4PSmDVAU8(B2wIm#IdHae-F{3jKQFiX?8NlKEhXR2Z|JCUd@HMnNVwqF~V9YJtD+T zQlOroDX-mg2% zBKV^Q5m5ECK{nWjJ7FHOSUi*a-C_?S_yo~G5HuRZH6R``^dS3Bh6u!nD`kFbxYThD zw~2%zL4tHA26rcdln4^=A(C+f9hLlcuMCv{8`u;?uoEVbU=YVNkBP#s3KnM@Oi)fQ zt_F3VjY)zASub%Q{Y?XgzlD3M5#gUBUuhW;$>uBSJH9UBfBtug*S|-;h?|L#^Z&uE zB&)spqM89dWg9ZrXi#F{KtL@r9g^xeR8J+$EhL~2u@cf`dS{8GUC76JP0hHtCKRg0 zt*rVyl&jaJAez;!fb!yX^+So4-8XMNpP@d3H*eF%t_?I|zN^1Iu5aGBXSm+}eCqn3 z^+vzcM*J>wV-FJRrx@^5;l>h0{OYT)lg{dr8!{s7(i{5T|3bivDoTonV1yo1@nVPR zXxEgGg^x5KHgp?=$xBwm_cKHeDurCgO>$B$GSO`Cd<~J8@>ni>Z-Ef!3+ck(MHVy@ z@#<*kCOb5S$V+Fvc@{Qv$oLfnOAG&YO5z_E2j6E z7a+c(>-`H)>g+6DeY1Y*ag-B6>Cl@@VhkZY@Uihe!{LlRpuTsmIsN4;+UDsHd954n9WZV6qq*{qZ5j<W)`UorOmXtVnLo3T{t#h3q^fooqQ~A+EY<$TDG4RKP*cK0liX95STt= zToC<2M2*(H1tZ)0s|v~iSAa^F-9jMwCy4cK0HM*3$@1Q`Pz}FFYm`PGP0wuamWrt*ehz3(|Fn%;0;K4}!Q~cx{0U0L=cs6lcrY^Y%Vf_rXpQIw~DfxB-72tZU6gdK8C~ea6(2P@kGH}!2N?>r(Ca{ zsI!6B!alPl%j1CHq97PTVRng$!~?s2{+6ffC#;X2z(Xb#9GsSYYe@9zY~7Dc7Hfgh z5Tq!})o30pA3ywg<9W3NpvUs;E%Cehz=s?EfLzcV0H?b{=q?vJCih2y%dhls6w3j$ zk9LB0L&(15mtul3T^QSK7KIZVTod#Sc)?1gzY~M=?ay87V}6G?F>~AIv()-N zD3rHX`;r;L{9N|Z8REN}OZB&SZ|5a80B%dQd-CNESP7HnuNn43T~Agcl1YOF@#W03 z1b*t!>t5G@XwVygHYczDIC|RdMB+ z$s5_5_W-EXN-u_5Pb{((!+8xa+?@_#dwtYHeJ_49Dql%3Fv0yXeV?!cC&Iqx@s~P%$X6%1 zYzS9pqaUv&aBQqO zBQs7d63FZIL1B&<8^oni%CZOdf6&;^oNqQ-9j-NBuQ^|9baQuZ^Jtyt&?cHq$Q9JE z5D>QY1?MU7%VVbvjysl~-a&ImiE(uFwHo{!kp;Jd`OLE!^4k8ID{`e-&>2uB7XB~= z+nIQGZ8-Sbfa}OrVPL}!mdieCrs3Nq8Ic_lpTKMIJ{h>XS$C3`h~ z?p2AbK~%t$t(NcOq5ZB3V|`a0io8A))v_PMt)Hg3x+07RL>i zGUq@t&+VV`kj55_snp?)Y@0rKZr`riC`9Q(B1P^nxffV9AvBLPrE<8D>ZP{HCDY@JIvYcYNRz8 z0Rf+Q0riSU@KaVpK)0M{2}Wuh!o~t*6>)EZSCQD{=}N4Oxjo1KO-MNpPYuPABh}E|rM!=TSl^F%NV^dg+>WNGi@Q5C z%JGsP#em`4LxDdIzA@VF&`2bLDv%J)(7vedDiXDqx{y6$Y0o~j*nVY73pINPCY?9y z$Rd&^64MN)Pkxr-CuZ+WqAJx6vuIAwmjkN{aPkrJ0I4F5-Bl}$hRzhRhZ^xN&Oe5$ za4Wrh6PyFfDG+Nzd8NTp2})j>pGtyejb&;NkU3C5-_H;{?>xK1QQ9S`xaHoMgee=2 zEbEh+*I!ggW@{T{qENlruZT)ODp~ZXHBc_Ngqu{jyC#qjyYGAQsO8VT^lts$z0HP+ z2xs^QjUwWuiEh863(PqO4BAosmhaK`pEI{-geBD9UuIn8ugOt-|6S(xkBLeGhW~)< z8aWBs0)bzOnY4wC$yW{M@&(iTe{8zhDnKP<1yr9J8akUK)1svAuxC)}x-<>S!9(?F zcA?{_C?@ZV2Aei`n#l(9zu`WS-hJsAXWt(SGp4(xg7~3*c5@odW;kXXbGuLOFMj{d z{gx81mQREmRAUHhfp#zoWh>z}GuS|raw1R#en%9R3hSR`qGglQhaq>#K!M%tooG;? zzjo}>sL7a3M5jW*s8R;#Y8b(l;%*I$@YH9)YzWR!T6WLI{$8ScBvw+5&()>NhPzd! z{>P(yk8{(G&2ovV^|#1HbcVMvXU&;0pk&6CxBTvBAB>#tK~qALsH`Ad1P0tAKWHv+BR8Fv4!`+>Obu1UX^Ov zmOpuS@Ui|NK4k-)TbG?+9T$)rkvq+?=0RDa=xdmY#JHLastjqPXdDbShqW>7NrHZ7 z7(9(HjM1-Ef(^`%3TlhySDJ27vQ?H`xr9VOM%0ANsA|A3-jj|r`KAo%oTajX3>^E` zq{Nq+*dAH{EQyjZw_d4E!54gka%phEHEm}XI5o%$)&Z+*4qj<_EChj#X+kA1t|O3V@_RzoBA(&rgxwAF+zhjMY6+Xi>tw<6k+vgz=?DPJS^! zei4z1%+2HDqt}Ow+|2v^3IZQkTR<&IRxc0IZ_-Di>CErQ+oFQ~G{;lJSzvh9rKkAiSGHlAB$1}ZRdR^v zs2OS)Pca>Ap(RaSs7lM2GfJ#%F`}$!)K4#RaGJ_tY}6PMzY{5uHi}HjU>Qb~wlXQ) zdd(`#gdDgN_cat+Q#1q&iH{`26k}U3UR5(?FXM>Jm{W%IKpM4Jo{`3aEHN)XI&Bwx zs}a_P|M)fwG1Tybl)Rkw#D__n_uM+eDn*}}uN4z)3dq)U)n>pIk&pbWpPt@TXlB?b z8AAgq!2_g-!QL>xdU4~4f6CB06j6@M?60$f;#gpb)X1N0YO*%fw2W`m=M@%ZGWPx; z)r*>C$WLCDX)-_~S%jEx%dBpzU6HNHNQ%gLO~*egm7li)zfi|oMBt1pwzMA$x@ zu{Ht#H}ZBZwaf0Ylus3KCZ*qfyfbTUYGuOQI9>??gLrBPf-0XB84}sCqt5Q(O$M& zoJ+1hx4Wp#z?uex+Q1crm2ai?kci;AE!yriBr}c@tQdCnhs$P-CE8jdP&uriF`WFt>D9wO9fCS0WzaqUKjV_uRWg>^hIC!n-~q=1K87NAECZb^W?R zjbI&9pJ)4SSxiq06Zasv*@ATm7ghLgGw3coL-dn6@_D-UhvwPXC3tLC)q3xA2`^D{ z&=G&aeSCN)6{2W6l@cg&2`cCja~D2N{_>ZQ)(5oSf!ns1i9szOif~I8@;2b)f2yQ5 zCqr{lGy5(^+d!<0g??wFzH^wuv=~0)g55&^7m8Ptk3y$OU|eI7 zIovLvNCoY%N(aW#=_C%GDqEO|hH3O9&iCp+LU=&CJ(=JYDGI;&ag&NKq}d;B`TonC zK+-t8V5KjcmDyMR@jvDs|7lkga4>TQej$5B+>A`@{zE&?j-QbQWk4J*eP2@%RzQ{J z?h`1~zwArwi^D7k9~%xtyf(2&$=GsP*n-fTKneej-y6y(3nNfC7|0{drDx{zz~cSs z<_+d2#ZDst@+`w{mwzmn?dM2aB;E;bS-Opq$%w@WnDwa$hUGL90u9c=as)+_6aO10 zLR|CR8nr<2DQTvkaH0QDsyn@TYCs7Nk3lN}Ix$)JM0*zf=0Ad$w9j723W#%{r8V&`{wx-8kSv#)mZ{FU%UZDIi zvbgLHyJ>z0BZe`GNM$Q;D6D48#zc9s(4^SGr>u-arE}okN62N{zuwX)@FL5>$ib=b z5Wtm~!ojD3X|g59lw%^hE?dL;c^bgVtBOkJxQR{Eb*nR1wVM&fJQ{<))bn9e3bSlu z3E-qpLbAE(S^I4mVn`?lycoV!yO!Qj_4qYgsg7tXR)Gu2%1)5FZu&lY7x>bU`eE}x zSZ5c`z~^&$9V?eEH!^Rp-Fz3WiCvEgf`Tq}CnWRZY+@jZ{2NewmyGUM6|xa3Sh7)v zj6d&NWUVqu9f-&W)tQ>Y%Ea!e76@y!Vm*aQp|wU5u<%knNvHZ!U}`fp*_)mIWba=j z*w9~{f5pD;zCmEWePjM#ERNiNjv!SnM-&rGpB9Nmiv}J+hwB&0f_+x?%*lgJFRHsqfFDPwyvh8<*xLT0u_BeEHw{q+UGj=$4udEx)Vq#sV zKB3+_C!RUKy?ac3-`+}dL2!D_2(5=8&@hBf`-AbU`-<_3>Ilqkg6qSI>9G(@Kx?g<0h0K&31$AR>R%d}{%DyXPss$&c^ja7NR z$0AN7Fl$>VpGxqHW15CjxAa6DUVmCpQNbOwBv8D^Y{bXg28> zEQE9xl?CWh0gS6%Y=G4Cy($Vb>jBb2f_dm#0_B<_Ce`|~Obt_Xp^nkR zK%o_`{h1XkWn}i|5Dp#q8D(;k;2|+{DAG{2gJgPNQ=KZ=FKY@d>QEu6W;oLsE(1}< zpnwSEj(K{Bu^#CXdi7L_$!X`QOx^tA1c{&-XTHo3G?3(H*&VM~*Aud?8%FU=dE&kV zJ$SqZoj^g@(q9x;7B30J$(-qUml{?3e+I^Cf?X0PpLr}m zS}W9`QaCwINRU&D5>j9O*j6S}R1`7{5+{d-xUlI~)U!^4+*b5tkuon-Msz03Z{{Kp zH!GAXoyr#1K;t5o#h#a%Lzj3XQGqM0TRnfu$(fsQe^wb_?W!m!+7r55q>svWN`k~T zS(gk9bi|@+8wg;dR<&0f;MpwQbY27$N{{laPQk3@3uCz$w1&jq)`uW*yn!Pe-V^%Q zR9)cW;UB~ODlwolWFAX?ik#_|v)AtHNwoq72E9Jg#v2e5SErf+7nTleI8&}%tn6hf zuz#5YtRs94Ui&E_1PakHfo+^t-{#ewhO*j5ls-zhm^C{kCARNEB1aORsxE!1SXBRz z6Oc-^#|0W6=7AJ;I|}pH#qby@i^C+Vsu9?zdtkE{0`oO_Hw|N=Lz9Is8j}R zI+8thGK?(KSZ5ZW4nQG1`v(=0Jd*0gIlavVihzo#fPaa=}(Rqdxl3^6O8K+{MqU`;1iTJ$<^k)Nms(A$j?A-wHJKvh9 zUHW3}JkE;x?FETPV8DFTxFLY8eSAd%C8vp?P_EuaMakmyFN_e?Hf|LBctnncUb}zF zIGP4WqtKCydoov~Bi<_I%y%$l+})!;SQVcP?>)9wM3q-GE6t9*LfoePBlo{gx~~e{g_XM5PQ8Y5dsuG%3Xq}I&qcY6 zTCo?<6E%)O$A2torq3-g8j3?GGd){+VHg@gM6Kw|E($M9}3HVIyL1D9321C zu#6~~h<<*=V7*ria%j^d5A;S^E;n!mOnFppfi+4)!BQ@#O2<|WH$RS~)&2Qol|@ff zFR#zmU(|jaqCXPA@q?UhrgbMO7zNXQYA@8$E+;4Bz7g=&zV-)=&08J_noLAz#ngz$ zA)8L8MrbXIDZuFsR_M(DsdX)s$}yH!*bLr{s$YWl5J?alLci=I#p`&MbL4`5bC}=2 z^8-(u4v2hs9*us}hjB!uiiY6vvv&QWJcVLTJ=SFG=lpR+S4Cd91l}oZ+B-*ehY2Ic_85)SRSa% zMEL~a3xrvH8ZnMIC!{9@pfOT7lrhxMf^8N20{CJXg}M35=`50S;6g-JYwjwj!K{^) z5Bohf6_G6z=+0V8&>F8xLbJ4mkCVu^g66#h&?tL z9odv&iW21IAh~y9D-DupKP-NcernF2(*RsFkAsM<$<>@-Cl1?&XAi4+Mh2Zm@2x#u zWH&J^1=8G|`|H2%94bnjUZyI>QACu9FS}^$lbtzzCz4AMspqGYEwFFM<%G!Oc$+;7 z3r_L!H~PR}5n8+3-&4v*fFr$uK{y_VamM0*TKn^))nQsn5U?7Iv?`4|Oy&m6himAG z%=a;2ji3f_RtDPqkwR>ISxhnS0f)E`ITo}TR!zIxPwECZy#jzo%q{BNYtd!<IP_S+=*yDOk1GgwLqe!d9esV@3$iVAm1!8RoE| zqnTz;5a)B(~~KcP)c>?+ysFAlAGF4EBor6)K{K*Kn>B(&QtMAkR^ynG%k%UbJpKM zI$}qQXXP3PISHe_vTFssbcL`irhG2zN7J((3ZFmh*bnPuiK~=#YG=820hXqOON#HI<0bvIT{z&SaqRvqaMG-d5<06zdP?-kIH{%UMR$Xn@S}Hx3 zFjg}6no}vN_512D+RIn-mo9^_Li-)WI5%VigYt{Jd!RyI%d|-LqJU$y3aJ*a$y6$1 zjyTuIF2&t>1rPlw&k5OVLhrYBvk5Vl8T(*Gd?Alqi}> z<@-`X_o@9EOB8Ik&?|;lvKHFU@#O+?T!kEf&oJUaLzN;>!}!!e1WIs(T}V#Irf$AK z42`x`z-9ogxd@%CS;D5S z2M^b;Pu)q)c&_KBO!va-4xnI57L7V@*_I_r4vU)z>xk5z6PDVqg92R7_iZH|VlO_B z#8R`5HZVn?ou>czd>gZ~s;w4ZkzVXJNP8FiezlB5JXe6Z-OLsDw%N7!(135!Vl2Lb zLYI79?U{h#W-_#W6hf`<$BQHJCu5ehv?IF+-uxUqt~j!ZW1cxfiEJal^q7~RMWQ0a z2CEaPa1_p|P6qRmmeKgas*N}@(2tH%U37-<5i(DSnVOFFxg-Sv%7&{hPeRh{U`&ufGz=V|JdYQ2sG5 zk%3JimSwQFP=Yr?u_beSG^B$nnh$4hrxb4lpTTiUFRQEZ3ulr+L3m;>;Io?D;jG6Wjj!b)nsZds<6 zX@cD%+aVr!ra~F7HYr`TB!|y-t)HSb^FQt zbo+_XP44IWJGGxg73JyhBjKMSv`77ngDOw}6Eve6ZIol$Q5s65d(1-sP{BU{1_y)7 zF8sh5A~jxRHk=wq3c5i3*e&otCd9>cstT?IQ&D4slC-&^q!ut1;WAQ}fE}Y+jU}r{ zmpSI%sW?})RAm8}$WUU+V$PmQOF5gSKOGQ2;LF-E(gd<67rYu2K| zom8mOppa%XJ6C(@I7-*opqLn73e9BMFStaBER?suJ{jte1$vA%z?$_`Em=a=(?T-q z*A=VZOQ`P{co!*UUKyV@Rd-c#*wmb7v<%rN=TGFmWmqhbj#&+?X|3bZYAjbNGTv~O zs7SIYi3VgW6@?=PGnbNNZIWaY^*+ChW&a)A$uqH8xxehwx2`<1w6mag?zuHbsVJiO$a)tQ zuBBoR>rLfhpA@)Qf`8BwRMx886%9HP5rOR%YCy9pQ|^Xw!=Mcnwx8j=(ZE)P-tJ&s zON&Nsr%14jS@K+IvrJj720NkCR*C(j&aI$EFCV)w$9M<#LdihyRKdzTjJPI|t9_S} z--#oF#;F?Y1KN%_yE);Bxv}9PWZphz_g5mReOKR`y%9UZ=n}GXWw?E$T1%NAfK1Ad z|0$Lp^;sntA>}=ybW)mkxNv1?hkZ`<8hCemcT5 zYl6$I^bhXDzPlz<>6zOy3Fu*3?>#q$;1fJ>nuxyx#&<&x6Y}j zCU&VmtCJ`;aYN+qP}nwr%s2ZQC|Z**axS^?iGu+x^{{>FIv!k0#HaXtEG=*C7kPe!mMnknbn}TKpp6Xv9 zVvq&%A3nmY^N*XTg&+=wO>(|{uTwm;ZP9@+M)6%T zwXPh-&{+aAfv^ZCzOEb;yj>A=f5Pbu)7T{9PT3u>#w*%?K8jqEF%I>A?q;E%CXn)f z|0ohNa5DMv@HVk^vT(L=HBtH*Vzo81L?)M=g7)>@j*vUx?S zxqZo23n3vn@K-Q@bx3lLT+5=fB_oz8+p?P;@*UU<-u)jb5WFEXzoc+8*EC5P6(HWr zY$mfFr=L&G>(jvl8US2fLQqTzHtAGizfR*;W4-kN2^I>L3KkXgx=e*}+i*N($}{?c zi=Q67G)oEMW{|Gdsm{)|V)5Evo}KLj%}gIe>98FFoNTLrJX z-ACRdewnT1w#Egct%wpGg~q%?!$}>$_UJPC4SP0^)G_$d4jN0jBEx}+rcd*^aDtnx zewG{`m!oSbQ?A~FZ6L{&V0hUE+b$DxjO_;oskFha>@gzy(jDnzGO>z3Tzz|i&Dakg zFid5$;SFxINis^4JzK5XIVabKoP`=ZWp|p|t{hTi8n|#XE=-rINwJ*blo?=%Se(qw zkW7x5Qs(LV5RVGxu2e&4);c73lY#0(iZo1x=MY;7mW`uUQIY+$_PqH`4a`6O#urwU zE6(FrvyExmB{c5z*YAj_P&t??F1t6TN2N!$N#~02u(t(PDVyD)$mL3hqKQ4E91N#GOIngPr&pUb-f_Z4*XV8`p1pq+mzrUlUY=4~i|3RDo;Lo36U}uwm zaOah}mO8c@%J*~~{Up7_7->8|3x<}WemgaMA}h>xD17Fey@V9;LgjQFSBS(A<+2kCP9( zlkD%;oXzWtZ_hgu0IxeTjH`6=vi|t_04Btl32=g8swD1oZguWr4|lx0RuXoDHbh27 z+ks?gkVWYnr~_{h+PzQjQ(#8kaJai4We{F!JuqCzU0t*+H{n6i3;K<>_6XUn1n)}) zJ?}JCUPYhT9S1Hi-M+$(Z**%fz7Z%IiMN6%kD>wh%r4#C?Ge4{>w9o??Vbehy9!3@ zffZs8?LGxyWQr@yB(|%~Aa>fVj3$O=i{K*f;?h-a@-ce{(cY8qByOCA1r0;NC}}gr zcC^fCa$Ot`42n>`ehclOAqBo7L&D6Mi=;M5!pd@jj$H z?U7LQWX_u7bHpBzF7L-s4*`C)`dUrbEIgKy5=QHsi7%#&WYozvQOXrNcG{~HIIM%x zV^eEHrB=(%$-FXVCvH@A@|nvmh`|agsu9s1UhmdPdKflZa7m&1G`3*tdUI5$9Z>*F zYy|l8`o!QqR9?pP4D7|Lqz&~*Rl-kIL8%z?mi`BQh9Pk9a$Z}_#nRe4NIwqEYR(W0 z1lAKVtT#ZTXK2pwfcCP%Apfo#EVU|strP=o4bbt3j zP?k0Bn$A&Xv$GTun3!izxU#IXsK1GQt;F0k`Tglr{z>v2>gCINX!vfs`aqag!S*AG5Z`y-# zUv_u&J4r;|EA`r!-gsoYGn<^nSZLH-nj1SRGc0MRG%LWVL)PckFn9z!ebIJ}eg+ix zIJo7GN;j1s$D6!({bYW)auypcB~eAWN;vhF%(l=|RR})$TOn;ldq^@8ZPi<%Xz~{Z zQQ|KAJ@JHaX!Ka2nhP%Cb^I}V6_C|e1SjOQpcPMMwfNz#U@Az|+rmH*Zn=cYJu-KR z{>f++Z~P=jm)4-7^yc#52U4qeNcBRYb!hhT3Q7Ngu5t@CvY*ygxu^Eh?2l6= zhdqN{QEaP(!p>1p1*toD!TllHH6EH~S%l9`mG62dyAd+?}1(vf@N*x^6vhEFU<-RqS7#12*q-xtU z5d|F^n%WSAQHnm-vL)4L-VvoUVvO0kvhpIg57Wf@9p;lYS5YfrG9jtrr?E<_JL{q% z7uPQ52{)aP{7<_v^&=J)?_|}Ep*`{dH-=cDt*65^%LodzPSH@+Z~;7sAL}ZECxQv+;z*f;(?k)>-Lp@jBh9%J`XotGJO(HcJc!21iZ98g zS-O!L9vpE(xMx1mf9DIcy8J5)hGpT!o|C8H4)o-_$BR!bDb^zNiWIT6UA{5}dYySM zHQT8>e*04zk1)?F99$dp5F^2Htt*jJ=( zH(#XwfEZ`EErdI~k(THhgbwNK9a(()+Ha1EBDWVRLSB?0Q;=5Y(M0?PRJ>2M#uzuD zmf5hDxfxr%P1;dy0k|ogO(?oahcJqGgVJmb=m16RKxNU3!xpt19>sEsWYvwP{J!u& zhdu+RFZ4v8PVYnwc{fM7MuBs+CsdV}`PdHl)2nn0;J!OA&)^P23|uK)87pmdZ@8~F$W)lLA}u#meb zcl7EI?ng$CAA;AN+8y~9?aon#I*BgYxWleUO+W3YsQxAUF@2;Lu-m#U?F(tFRNIYA zvXuKXpMuxLjHEn&4;#P|=^k+?^~TbcB2pzqPMEz1N%;UDcf{z2lSiwvJs(KhoK+3^2 zfrmK%Z-ShDHo^OUl@cfy#(cE=fZvfHxbQ!Chs#(vIsL%hf55_zyx>0|h2JT=|7JWo z+Uth3y@G;48O|plybV_jER4KV{y{$yL5wc#-5H&w(6~)&1NfQe9WP99*Kc+Z^!6u7 zj`vK@fV-8(sZW=(Si)_WUKp0uKT$p8mKTgi$@k}(Ng z#xPo-5i8eZl6VB8Bk%2=&`o=v+G7g|dW47~gh}b3hDtjW%w)47v#X!VYM}Z7hG1GI zj16;ufr@1^yZ*w3R&6pB8PMbuz%kQ%r=|F4+a!Gw2RBX6RD5c!3fU@+QCq#X7W@Q5 zuVQ}Uu0dzN+2mSX5)KV%CsU;2FL%B6YT`10$8JR^#;jOO1x?t()Q_gI zxpQr2HI0_^@ge0hNt&MQAI`yJ1Zhd-fpR{rdNmRkEEDu7SpB)QOP4ajV;UBZZZK<6 zWds;!f+|}iP-kqWAH#1@QisJpjcg`+s80!LhAG@(eMad|zcln~oE8}9l5!K{^zf~( zd=HArZ5+Mryc$uNa`@|GSdOX=y}8GZc-%p8W@OM)uk2DfmhQXCU1E#y3XJ>|+XdW2 z)FQLeK38}u_D(5E{GV|YT^rI4qds2{-r<@@@@SG@u&4LbC z5o|KKqVM{?wk$5>2?t*I?IHdh~gljn_2m2zqZNJEEz4Mb$o&I3_UAg#$B{0u$uF4-q}{ zzs5+k@qOe08!CGLGmy3eRrcuqsgB*B>i8c3>3=T^Hv>nL{{u)jtNc6tLbL7KxfUr; z=Pp14Nz+ggjuwd~*oRJ)xWwGwdge+~b!E%c3Gzw6`vT>CCxE0t6v5Z`tw1oKCcm68A~Dbc zgbhP6bkWwSQ=#5EsX*O9Sm^}EwmQQzt2V2phrqqe2y)w8;|&t6W?lUSOTjeU%PKXC z3Kw$|>1YrfgUf6^)h(|d9SRFO_0&Cvpk<+i83DLS_}jgt~^YFwg0XWQSKW?cnBUVU}$R9F3Uo;N#%+js-gOY@`B4+9DH zYuN|s&@2{9&>eH?p1WVQcdDx&V(%-kz&oSSnvqzcXC3VsggWet1#~bRj5lBJDo#zF zSz))FHQd8>3iSw{63m`Pgy_jkkj9LTmJ&!J(V0E~&}HJ4@nXp<(miz$sb;(I<8s!7 zZyezu!-+X81r03486gAlx@n#aKx_93DREBtNcYln*8oliQ zbh0~SkAgHXX%C6}HwN(TRwaK2k_$Y}PxKId;jYt=S1Bf<8s@(IL?k3u1(f^V%TYO1 zA_jPf*V)SLEZFWS#y>M&p$LoSk+%ubs`)H%WEZf=F)RKh&x;i)uLIGJ94~A4m$(;S z;1rQC{m>--`WHFcaFA&5#7~vz|5S;{fB(7pPnG;@$D~C0pZYNEG?B8X*GB2e4{Qk; za1oop8OvHqs1Lk6B`AuYOv4`y`IgM315iTr{VUVc9WeOG;xE z%eDQgE4rb_B%vuT>N?^K zRvPnQwG%7RjO26+DY!OXWjgBu4^!)W-+ob_G&nX++))pD->QdRCo0spZN?Y*J#@-q z)fk-fJvZYz8)GSxYc^oXYIM;Pw}ftHW+a3dis#dXx^OS^m-~FlwcVr6MXv78fNI!i z51K-2t&!&IZ4(GF=mT@;qIp!&R(I@UiWPPz)%Us&(FdAAGxZ-+6^UZ7em`J-F#_3r zLkHym@VAnZFM$J~?0b@&O`l4YXyvOQ+OqalbZ0{g{qD{neY_xno1ZpXlSJWM=Mv(~ zvK{?O>AcXpbd}+hn{~*>weZwDTURX*M^9RkOO#DUfRW1;comKg1bn+mlsrNY8XDyW zgWg9~AWb_1^D8zsD4bL(1J4oinVy0Fimrh&AC}Itl;IH*p4eU_I;SWkOI!9tAbi3B zO@0=q#LHAc>z?ve8Q&hsF(sR9lgf_99_5Kvuug<^&0}Y&m)YjI?bITGIuh}AJO|>z zc*`Mly$>TA={AIT#d%JuMpXHDt($qkc*3UTf-wS$8^awqDD^|EAeA{FoeyJfWM@QX zk>vJ4L|8DU7jg_fB^3Qvz*V$QmDl*AXdw6@KSckh#qxjLCM8Nba!dTkJgr(S@~Z0a zt8%|W!a~3zG4Y&X6xbLtt^JK5;JT($B`_9bv(BjRTfG_Y`tg3k-}%sQoY@F|=}}${ zwmW%Ub6jPd)$;NA0=b7w!^2dE-qvI4)AVr`yvkabJcGwvuQ2rAoRlTjvCC^-$2BG} ziy0<6nt8;J67rymwm&wVZ8E7Krouv2Ir@-GQ%ui6PR42KHKms3MK&Z$zp{_XAVvrd znK4cbg)Ggh5k(4SlFOM9yyRUlVH1oo%|6Lu9%ZxZW28!c9Z%H5#E?B?7H7ulcUtirB<{s@jnS(-R@we z^R#{Mn$#JXd~5sw9rU&~e3fYTx!T&hY{S<~7hviG-T$<4OPcG6eA0KOHJbTz^(`i~ z_WON4ILDLdi}Ra@cWXKLqyd0nPi06vnrU-)-{)Xp&|2gV>E{Uc>Td`@f@=WYJYZ^- zw&+fjnmyeRoK-unBVvX>g>wO3!ey<+X#z@8GNc9MD}khMO>TV{4`z zx4%!9|H6k|Ue;`M{G6d!p#LL+_@6WMpWgF7jk*%$D_JB3c%D`~YmHRJD1UNDLh;Tf zYbbKcv9R(81c4yK+g+1Ril{5w#?E}+NVz>d@n48C-T-(L?9a9W`JV*{dan-sH*P3_Hnt~iRv)}ye;7$b}^4l%ixphDK`G#b!4R4qoouT@*A zZ)kQa)e94??k7N>tqoRl>h(9DFq&92=z|F!LJrh-97EoFL|Wt2v}>(zG1*#aiYA_^ zM_&%_G^g*O8x650e>m!#MDmwRub!irY>^^|L=!4^%lBr;?}mvgP3y~^mSdKSm^R~WAt7T0_ck0mA`GS)J^SYTo6^vQ|vuM7!92&@$BhtcQ^Z4h2)aN zh~EQthyjn1(eI~$FtuHH!|x(iHU{9k40k5nPBwB)X@8Lo$P6u81EeoNOGRct%a-LM_4y3Ts z7ki0PWAO^Es6c%M*SSRn)2|NAoUsKyL%))uVx7?5lkrk`njxs4q@M~x+8%jr7xV;- z|KC=g3aTZO|y|g~oHXB6b42(|J_&fP2Y`*;L07H2d>{~JP zFNGl$MYUG(Qy3dR?9Bfdg8#peGRiVP8VYn@)6T1bj*v)s6q*7<6P(ZVm4ZnTA;rOHSd>P`_5uT0+azWdV`gIvLaJ1o*DB}&W6LCgX|BycgF5qd z!)}dT#A~4*6{1=Bd5VV(Qa2h4x9m#2X711z(ZN>i&cn`BopG*5P`CD*HfYiQmXNGk zhgqcHPBrJP$Z@PLZ4}d-8^}%X^LtUDHq&;~3}lUyrxxl@|IS={GP&6-qq&Iy5gKW- zC@$}`EEZd}DOSeSD+v_x5r_tpBWfN0gDa21p(@TAIrgWQFo7NO@slI6XOAML_lN;3 zEv~}LlMbGWKu}0s$tO-vR)wD!=olGcA?}vU;lRu4+Zf z?nCD7hBmA5`U9P#W8-*0V1=OT-NI0k&_`UZ87DbpYq_=DBdyNDchZ<|V1f%dbaa7i zf~R+6Xt%G)VXlM@8REfP3u#7UPadWYOBMsQ56fHRv!0p9R6q>Rbx!n|IY0goLb%{+ zzy|5WXk+(d@ChzOWatIV1lc1F!(uEOfEmMd;v`|$Kt3X2Uws;%@OV!E86PN?CeHV& z=4#TX{J8RWaH`)!J<8AUs#Ar{6Am^8M{S( zc%K7y2YbcLUz+*eDTXdthNE)Lm^P&*e^eV zilOS9)TVKgr9_^_M!TJ^44v<YF2NO=h(oOr5jYxVTxWk0XJ8n0{F_SOH%49WMk*Sg7`g6B(=^< z*rLAW;8I5;1?;Fh{N=f;kxjLpj}u^mD|k8lih|G4#}wEG1j`HIG( z8y;BMR3cE01e?(+k8NLR|Z+)#>qR^iMZc=BkcixWSKYmkaHpIFN?s%*74kc&wxwB zrtbYBGz9%pvV6E(uli6j)5ir%#lQkjb3dvlX*rw5tLv#Z>OZm@`Bf2t{r>u^&lRCg z11*w4A;Lyb@q~I(UQMdvrmi=)$OCVYnk+t;^r>c#G8`h!o`YcqH8gU}9po>S=du9c*l_g~>doGE0IcWrED`rvE=z~Ywv@;O-##+DMmBR>lb!~_7 zR`BUxf?+5fruGkiwwu|HbWP^Jzui=9t^Pmg#NmGvp(?!d)5EY<%rIhD=9w5u)G z%IE9*4yz9o$1)VZJQuppnkY)lK!TBiW`sGyfH16#{EV>_Im$y783ui)a;-}3CPRt- zmxO@Yt$vIOrD}k_^|B2lDb2%nl2OWg6Y)59a?)gy#YtpS+gXx?_I|RZ&XPO`M!yl7 z;2IS@aT4!^l`Tped5UGWStOw5PrH#`=se%(ox%gmJUBk18PsN$*-J8S%r51Y$i!4N zQ!rW%cgj44jA~_x%%smSTU2WG_W0c&PB$A5*kl8{$|865+lSIX~uyDT`uI7qnS!BPAg1Wwrc0e)8Usf zv9^E38H&hWSp5!@K8Qinl|)9 zEB?NMaxZK^GB!PUf1TBw+`H&jFSNI=Q@v5$Ryf-y^#IuXO#vsM5R+9@qz#z0fD0GP z9|Hj#E>?<=HTcsF$`xn`je~D&3kF1Qi%dfH{sKh!~(IpgjkDGQn zQx2F9rv{*x2$(@P9v?|JZY)^b9cd+SO6_1#63n-HAY3fE&s(G031g2@Q^a@63@o?I zE_^r%aUvMhsOi=tkW;}Shom;+Nc%cdktxtkh|>BIneNRGIK{m_1`lDB*U=m|M^HGl zWF#z8NRBduQcF-G43k2-5YrD}6~rn2DKdpV0gD%Kl{02J{G3<4zSJ1GFFSXFehumq zyPvyjMp2SLpdE5dG#@%A>+R3%AhLAwyqxjvGd{I7J`Iw{?=KKPRzyrdFeU}Qj{rm{351DoP_;vx zMo*s+!Gwgn;${(LXXO(xyI@$ULPZI|uzYR%`>MmW6Hcr1y2aM5b$grFwW_(9Fzz$Q z$&8dKNdWvBkK=iYWA|0}s1B7>8J$g*Ij_+S9vC1#jy~uA8nr)yY)a+ zoJ=e>Lp`7v3^tQN<&6UpDi{c1b}F~fJ$9r=p=@U^J_7bOck$5}ncVjYB0yEjbWrhe@E`j64yN3X?=k_F3BalH$aN zV=94?wDNv=BKLB<1*xU|65Zl!%51r5sHQ?qCggCw;$2QfCZ$lN40WPL=n^{Prf^QS zjbZ&1MRGgiZ2T)}DpiluFr#q*!AZJ$1v#d10YQ{>wQ5px!y28-1hCZ7lwvQnQYN*U zOg9BpvB0A$WUzFs+KWk1qLiGTrDT-0>DUpFl??l(FqWVz_3_Xzqg9vTpagp- zZcJ!5W?|0G%W|AJVVHJ7`u6@<4yyqMGHj@kpv`P+LV<)%PM__Rz&oq~t-*vV12@NR zoEVPz<2D>O==MlNI`;l8Gmv49&|1`FR!}2`NLRCqA{@`imLz6zrjS4ui0)O;!Pu&?KPAcX)?tDPS26uKvR(ry(p{6kiXPoZbnQ!vx6dLu zZCaj~Ocr$h##KqsD;9;ZiUwhmUd%5lrwczWr1Yn6V>+IK=>51;N7JDkrm1NY-ZBes z;FxeOTb^HAyA+~P2}WvSSu_fzt_K=(m4wUp%c*^hF zEJ+1dP0{0B8bryXR+qApLz43iu?ga<5QQxTa$1gMCBq0W=4|DTv4nY4T*-^Im%>U~ z)98;hc(d7vk0zAML$WnPWsqK>=O-FZSLI3_WQKr*PCK=(i6LelZ$$}XXrD5cb~VXz zT%egX>8e;KZs@jcD>cL9VP(Q}b0r~ST$Mc%mr1cC8mqRUQc|N^9@Weu$Z|KeczK7HhSFeFV0i)MQmwrn7CBL=p`_9n?nh320m}6-MSv3L7I*<*56GR zZ`zI^1zyC7F#*zVL@M)F2+oqxydaiQz?|ODmqs|Ub8%&KXk9P3P7<4tM?X{~!;Ygw zt=h7)AYGDO9F&wV=BhCyD9exr#YM_-<;Fo~iE>IBEXK$%;JCUAEr;lR&3S_DUy_E) z#!oCYdENVE9OaaeaIrPk-odMtvdFG;ocA#`L6AifMu0og^?Oy9F|Et9q6 z8;3_|9+Io@hqYoN;58x1K&OP!9Vd#dzhTRjB2kI?%31ceHb#Q~WqJV5lw;@b>4@Rd z={z1S`d05YdWC*RLc7sR0bVGSytn-a3`JZL3|d8KC?vj_70Vi4ohP9QbU&Q4?Zjd0 zSZA?KbqLBsJg(qj>fycto3`zN-)lDe4{Ij-QfoBn@rT_tTszA+CnM~xWmE(4zfpCQ z;zPJfl3=ctrggYM!KQg;V{J;utMMF9&BfOe!<{wU0ph?-VQ%cv3B%fFiW?6xBPdf0 zD-HhEU?0C`G@7e+b-=8fj=TP3mdz&SIQ}Nd`*G#DTz9Y@b zaoDF}Gx7ZhPzpDhi^fA7WZ)EAEFv;N2*bKp0T za0t<^1|Zc#`A+?s$!$8eO4CK~PUFECC3BwNR4f)!V&-Y>$xg(%T{MtrH|CPcO(Lf> zE_meE1?6S-qlV^p2fh! zT11Ub)hHw!_mpFDMIAFB`%Yal+`1IXV>b?%!q^Ps%8nh8wtjVGlF-!5x*D29WJ4=M zZ7X(QvKe$YZNgM(HibD7+VO5Q29?@HzS?k$c|3B@JI6dlLgu5S&LbU4=4p-Yn||z@ z4p05vq*k*pbOV9QjVTMp8`c$?t@~!$8&5AP_sz@tk%a$nWHMh-Gm{WS5+q)5W6pU# za@YZXJCLTpZ}zb=$HCYbIm->?Hu6XIBz_d7)n1+3eSLzGVoNQCTHcu9qS2@({0sxc zu<-mhx@Xz_*(S1DEL|d0`YV7uNevL*Y6|DAQmvSp{4DzPL@>hqJ?`FjvIU;<&}YEKDmFUGSBYjRmK{Km-1m%-t=fFfI9kV|POH|SxvO=P+><+1JK_lt5F6fTPf8PXU+lYEJz__** z&>`4F2F8EWE+k7ZsZx9%!?A56{lsk1juYw5zN)V+g$d^Q^Gm}fnHKA6L^36=`e;p% zp{;JD$X3%}O7qINR*2<>a422}_hmc=)-A7B-1#2v85jN5K31t0DtmqON-Dim`XIR; zOo`KRv)gtn?stp*`^f>}UDnGYGnJAbl(4srd>(5fo2#oqi>#bus86EHfeItFIu$+% z;lE|3gjQA`BXHEE5JdcjCoethN`@NEc~zm6CYf@LJ|hT^1>l}gRl7oDHMnw!*5*IC z@@Mi=gO=lZSnWln`dX^4Bd{9zYG{HNIX-87A#5OM%xu*%V?7K3j3CHcN*t!zNK4N4 z!U2?a>0`8m8}UQshILC0g6-k>8~;SRIJ?vQKDj z@U{DrstWIT7ufyRYox^&*IyHYb$3wtB}V^0sS|1OyK#sDc%sh+(gy&NT9j4Aa7J0C zPe$02TylMjad&|{_oe3`zx)Cqns?6qThYue6U=~j5+l0Po4`bX*&9V@a<-O;;vCzm z(af&;e<^}?5$7&MRW$eb*P< zX|33QmDvFSDFK-qMz|RF|Eedum@~W zt~8C1@i8@LammTr)rAgKm8X_SczCg@+@LeWpcmx;VL;iLQJ;t%Z*|XbNWUnHX|o=Q z%bsXc%bw=pk~8%3aV-w(7E$co9_cHQ$!}Ep6YcoCb7~GQBWl#4D!T8A5!P*tSl4FK zK2CX0mjmosg6TSK@-E-He{dm0?9h{&v~}OX15xgF<1-w4DCypYo22%@;uRq`ZFld- z{Uqof@a@P5dW@kfF-`1B1(!R>(DHb&$UXY%Gd+6r?w8klhP&ldzG*6#l#VuM&`)ki z)f$+Rp?YYog9u==<#MC%1daG#%3EOX9A{7$`_(s#_4mV`xZaB+6YlX`H4{}vq;)TF zo~fR@do6EZIR?413A$V6o^fq&QV7P(bB(9m1969szOosyhZRYciAWXe4@u-}s(LeJpuIkSx)XvjXmvVEseG zJvWN4s|$6r;s(3F+cgeh4DMEq??h!$eb^5h#`whT5d03qfYpol8dCim)A^NG1-H}} z!b)V8DTL2Q8@R2p`y4@CeSVj9;8B5#O?jfl-j<$Quv?Ztwp*)GvQ~|W8i6?-ZV@Lf z8$04U_1m{2|AIu+rd8KW`Qk|P1w(}d%}cjG6cxsTJ3Y&*J^_@bQgXwILWY7w zx+z)v81rZv-|mi>y#p$4S7AA760X?)P&0e{iKcWq4xvv@KA@EWjPGdt8CKvh4}p}~ zdUVzuzkBlU2Z+*hTK214><61~h~9zQ3k+-{Pv~w`#4|YdjTFKc{===9Ml7EMFmE!f zH}U3O{Z`DuJrBZbz~OjSVlD6uZSEeNK8epja_LanEh8v;_$Eg9?g*9ihMoat$#qd^ z?;x?a*y3-pW#6|kF^<$w;2^~s!fc;3D~#&#WYZfK@3;bO{MvmN?>qy%_%v`BVCgfC zdwL~(H14Gr6w(1CX|R;zhZh%?*Q{hxJH`MV2)@Jg$pbqjZeL+LO7^vwgi!@3yn@NT zU91-{;BWIi8bV-j-YR|A9Qs?M?e7Ru&Onl1(Sz(kxAw?LEbd+Le%Z43rZgb2h2m|e z^rblc;4r+}?@tC(YIBB_qpQL?_kg{;zO#6JD9{;HSUgf@zIZ)}Bh4wFZIs>meSd}f z4iF~nD$KAV6CVEw+{YOPrW~~y~Y=?snG4dE3edN$~SXh`!c_F zUsQ1M;ARz&v0mIbfP}aLWZ&cBPU+DU{l+0}_>9DZGL{@}lF6QCtgAg;EWUu`D$Evm znblG}kC!}Mw)bR~U;+S}T9TVc6lXWR!LNMm)nmxr*ORkv#&UO$_WQpt0WdX{A=bjC zV^lB~(r;y!C4$Rk0fWUR|09O?KBos@aFQjUx{ODABcj}h5~ObwM_cS>5;iI^I- zPVEP9qrox2CFbG`T5r_GwQQpoI0>mVc_|$o>zdY5vbE~B%oK26jZ)m=1nu_uLEvZ< z8QI_G?ejz`;^ap+REYQzBo}7CnlSHE_DI5qrR!yVx3J1Jl;`UaLnKp2G$R__fAe;R(9%n zC)#)tvvo-9WUBL~r_=XlhpWhM=WS6B0DItw{1160xd;M(JxX_-a&i%PXO@}rnu73_ zObHBZrH%R!#~pjEp~P?qIj4MdAx@sv;E96Doi$eO-~)oUz%Z0Tr4K`-jl06Il!9{s zdjF*1r{XU?)C(%XKPm;UnpnDGD%QL3pgo0ust~+sB0pa|v37>E1dp*Odn)n=DY;5j zDzSAkU9B6F$;|##_mrDe#%hd7pC1u`{9ZKeDdtkyl&4>H=e)Fq@}$UffPt1#cjYZg zd%O%xpg4~brEr>AnKT)kF@`cdX4tMlZ#Vk!l1Xz!G970p`Gkv^lk-|>jmt0W5Wu6woGf?hNA zXO2?BG)<{`NsYAY#3|L^x*=rS7uWU~s<*UhTC8AYc#lGP-=Aw1I)@y(<` znQb^nL~$rlDbsdAc4nc#{+$_;Z4iY;Pi0i9Q;>ZB3+IjWLg_r40-Fso^xF<*_s7Tj zujFrMH{vW3PmCndjQIscnQE%`Qj|E2kidi#c&PcWIMyH+e#7!l`<$_)*pDP$!49pY6w!bN)j8~A1wV%gIakf+vA04 zV)_Q=QMPSj6$M2Ar#KhhxsbZUOq3nZHh8m0?Fr}I6N(Fk zkhXM(f57yOa8vn^97J+g9ISPa=-**6^8ZX&g=z+m&6~x<1>)MyM&tpbWhSf8#+Pcd4rVK#)NSw>1eLKHTO z44A@sc_}Ypi#ggFRbDRFV(IhOnRU&XPrQYh9`mVMo-^U$&AwsXooSRUFqJ7)XUXCK zFpt;gJ}9QTN9xy9$=3OnRkjgUuQZ`X)!}LBm~WUIEKuK-Z%}f?2?+MKucWU<3)>9G zxsz~2pHut1AmH<@66;LdCB9+dSpojE4ggrYS?%icv*Rpi?G0Q($^`(g<1&Z){O_5B$@f#;I2-+Qa1P$a@=u-vOY5vqo z|6G67X;*A|V86ZET9OpFB&02twZtc2K}~ASoQpM_p{vJ{-XvA8UmQa4Ed%fS{D@g( zr_aY0gKw*=2SIGznXXKFo$r0x3)@bq8@4od^U(L0-jvTsK@qYOWX?2G_>N+?;r{TU2{M>V0zid zB_Zu?WSnRl@k?oE*gsgv;jH@+ z-}BDGyR-ls7$dz{e( ztv7lI2|OxNkLD4zc3xGA`!d7LiSdOys4H!8aA(_c0Nm*uLjS4TW%Z3v>am1nwQ_lI zIs85Uufd;cv-(4wi(Js;QsL#|qdv)n;r_?puaK*1>zTC@d=#sK+q1YF_Q(5B%%3TtI8&bNs_e8vIb;oc|Rk`F~u?|A?jj{c={?{Env{mW#q@8 z)#WEgt4B6b&X2?o3=b`ilz;)-h$t4;hsxPDo-%5C(7m#c9tZF-U`vcx0HnVtf_X(}4Tg}4wx(=y!@T7{)4;I_p95mBhikg-|U9z35q`|!1+Zz@97 z(PFE5jCv|=t;^=(CLqYp)k90rV4ZSiFDAhD8YOCzv{}1WDuB?epORibW36);q(Aig ze27@D?lN-ZyjuB4GsebA$;+(KGiOtCe6Bfd%GKRty>dBS1GUe}MXgnu61UdgO=m1& zE(eECPF_%J-lU{;R)eQJot;;}Wch$-8Z|lxN*AAdc;bkpbD`W}F=Z}^Cy(SKyfF#+ zQSalA%JDDAu|77$M3E|kv==3vx~pFPw_<+9xgcE#oigh*>#QsA2}sTYO7uY(h@dhR zHJBi^bb-`1?<1cGFZJa8Akzs{H^$N<)5@hlXeKwt9hD5^5K&`pdHOI92p<7XhS?>| z(5h9KYctN|H+W~Xh2N4W+yjMyBm(AdewjX?PBuRU$^J zS#+U($K6rhFFzf z0q*kJ>B6xI1qAti?H@X@dxtB7_vT+Nj@PNxr?CSK#xqE6jh5S{`nH#zzvjOId=i1X zK(Yjl!7KF(73GXYLVkQA5irn|v-ArCqwi)CM8X&m!#@NQ3bqmQlfurU4qT`zl_m^C zhpk?mfVvy9L|)*+bW8&NY4lG$@0_PKfO9+~(zrbn?wECGi7472W{H&dRPZum^Qf z73C-TR6$#q>XJgYnUgV!WkbmRas;`TY#7CxPXIEGwT6VPBDKbyr#|C2M%q|7l#Ql< zuM}j=2{D+?SxT8?ZJn&Z%cRN8Gu@y(`zV(lfj1T%g44(d#-g&@O0FL5;I9=?bW>!M z%c3J&e}GThdean-<||jUh zlLP`UeKBhhrQ?HHjM3}kfO7Z=EKB%+rs*t+nuBoeuD2yk%n32SA?-s)4+DsTV7U&K zyKQO2b2*tQT}#((=#fkb%hkRkt^%tY&VK$hcs91+hld zJ%lgC!ooILC&|(Z9$zzk=Q0*%&l7wwyf%nv=`C=OcPjb|Q%@9*XkPGFrn+bxp?t^D z!_qO=e-;bnT)^0d|Ex9X&svN9S8M&R>5l*5Df2H@r2l)VfBO@LqeVw`Fz6TSwAt^I z5Wu6A>LNnF7hq4Ow=7D7LEDv3A))d5!M=lT3ConlFN`5eTQMexVVs* zH0tx-*R+-B@&Lp`0V4j6Uy=LJmLQRY_6tH4vnV{_am%kkv|{CYkF}4Wn6U+|9Xre$ zJkO;_=dtw`@aEs|^GlO-zvpp-73H;PYk}V5RrH83G4SVkRJ0YSluQa8pKejcqB4u~ z^9^lDR|?7vEo|jITtaIFI6}1;vTI6n(d0kDGQUJuk>>sqdd7#VBF;?_dM5i<+VMEq zc>habJK}_0eEsOkdwv48d43jKMnqYFMnYDU&c?vi#Fp+S)sxo1-oVJ*g!X^^K! z>z!G8?KfU{qOnLHhaEF4QRHgOpfvoo7@=FG(2ZefYJk- zZuA9ubiTTP9jw9Uzpx8FfJBFt+NNE9dTlM!$g$|lTD za4LMNxWhw8!AV(x;U`IV-(bK@iQ%#QSmq8D$YqLgt?V#|~% z;{ST}6aQbOoewMKYzZT@8|Qq z@9SNBu1UErolMjrhJW-Id&7y<0I<+Z-lr`IHMh1;M)n@g|hx_T-maO`s{Tuhax}EjC zS;1kdL*A3BW5YZXgD|0zm)g3_3vMs>5xgHUhQDl19lfQWMcfLTsw$)amgDs>bW*Oe+$UK^`ioL%F0Ua5vb%II+EGS>*I zw)AmqcWBZpWH&Aswk_FJT=J|^Gn=MfnDTIzMdnoRUB91MeW?e>+C)g3_FDN8rN$(? zL+kH!*L}rq`MK`KDt^v4nUJg3Ce-`IW0Ph0?|}Puq5WIS_a7iEO;~mGQqqo=Ey;ND zhBXA^$ZrCc#&0}dMA&@)&TCq5PMzgJPafZCg-6$R zRqJ2+_t+dGUAY@~xPzU3`od7-(8nnuMfM-4#u`Q~`l-CUGC7u*^5VwH`ot;Ck#R1% zRr%?;!NrB$w^}NW=GGR}m!3a9bh#wXrq?fF7j-IS?E_!GaD3KYzcXhCUHhjEl-6b# zCmIF#4y@HN=^#uIz zRFl8D)Ri1<(Kr~Hoi_MtXWP8^AyTKxi1)ew88bV{*Ok8w8YLXBFW0sRJ<(vU{$ym| zz)feLQbz3k;_}2_{-bW`h~t&2$ObtlbS?k2k|5Kbu?FZLDMTVW_Z6p#A)c)`3DD?a*hxHS2Zj zcIiebfsINfWvwY7Z{YOlIQ61b`j=%6{>MPs+`()Q{wq0z0?|jwRN(1IrMQsj40BHx zvBC_Xfcr;55&}MeoP_@#nz$avCh%FJfE5NNAE~fW@L7~f8Y=?Wno31128EYOK8+O! zc4Vaj-DCsB6CPH$?pQQVbb_(tg^x{$STYM_WKLtrh-_-Hq-M%Ubpt6$mCHY!B{ISD zz}grIo^bNVDw4={SA2*nDNq5`e@ZO5r4TbQpHM)~qfD9!s0h(Jf>vYd;I~j<2fD4)_>ctbwNX6S*8>i^*4 zYKI5<4}d;hM!!N|A$@eg09J|HV;!UUVIau_I~dxZp#?a3u0G)pts6GKdCNk>FKxdh_`Xu!>zO3Kv?u+W6cYJPy!@=PuY868>3|Zg} z$7galV~M`d!q(`I{;CJsq6G9>W0}H6gVY`q7S@9s8ak1r{>}*Q0JyH&f!f8(NZxhC zkn|KS64r^A1fniFel2KkxYByk%erCx9UgFLI)`yuA)X z8SU?6kj!numPNCAj}>1ipax(t{%rxU;6`(Nqt$~Z4~76TQ$9d8l`yJ}rniII%HbH= zlS_7o!qB{55at^>N!Voer%)`KMh9Yd@Z?~nc19*hs)NGN954`O9zA&&vJHbm&|D@E za(&z6A=3NfC;>I)hlI@ulP8E@W-ziGe{iCf_mHvWGldxw8{ng-hI({EtOdALnD9zG ze)fU?I(DNt)Bzdd9Cs^>!|+2!xv1SK=I zJ+y_;=Sq-zqD~GKy@{5(my&aPgFfGY&_mayR_)?dF_^Fwc-n!UAG+fQQGfjWE-1MF YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b74bf7fcd..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/README.adoc b/spring-cloud-function-samples/function-sample-azure-time-trigger/README.adoc deleted file mode 100644 index fc5fc9d23..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/README.adoc +++ /dev/null @@ -1,122 +0,0 @@ -== Azure TimerTrigger Function - -IMPORTANT: For a general information about building and deploying `Azure Functions` with Spring Cloud Function, consult the https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html[Azure Adapter] documentation. - -Spring Cloud Function example for implementing https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer?tabs=in-process&pivots=programming-language-java[Timer trigger for Azure Functions]. - -=== Running Locally - -NOTE: To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here]) as well as the Use https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator[Azurite emulator] for local Azure Storage development. For the emulator you can run a docker container (see below) or use the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio-code[Visual-Studio-Code extension]. - -Here is how ot start the `Azure emulator` as docker container: - -[source,shell] ----- - -docker run --name azurite --rm -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite ----- - -Then build and run the sample: - -[source,shell] ----- -./mvnw clean package -./mvnw azure-functions:run ----- - -The timer triggers the function every minute. -In result the the `uppercase` Spring Cloud Function is called and uppercase the timeInfo and logs it into the context. - -``` -[2022-10-11T08:53:00.011Z] Execution Context Log - TimeInfo: {"Schedule":{"AdjustForDST":true},"ScheduleStatus":{"Last":"2022-10-11T10:52:00.003967+02:00","Next":"2022-10-11T10:53:00+02:00","LastUpdated":"2022-10-11T10:52:00.003967+02:00"},"IsPastDue":false} -``` - -The `executeExpRetry` handler demonstrates how to handle errors using the https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages?tabs=exponential-backoff%2Cin-process&pivots=programming-language-java#retry-policies[Retry policies]. -Sample emulates 3 errors on the first 3 executions and then continues as expected. - -=== Running on Azure - -Make sure you are logged in your Azure account. - -[source,shell] ----- -az login ----- - -Build and deploy - -[source,shell] ----- -./mvnw clean package -./mvnw azure-functions:deploy ----- - -=== Implementation details - -The `spring-cloud-function-adapter-azure` dependency activates the AzureFunctionInstanceInjector: - -[source,xml] ----- - - org.springframework.cloud - spring-cloud-function-adapter-azure - ----- - -(Version 4.x.x or higher) - - -The `uppercase` function with signature `Function, Void> uppercase()` is defined as `@Bean` in the TimeTriggerDemoApplication context. - - -[source,java] ----- - @Bean - public Consumer> uppercase() { - return message -> { - String timeInfo = message.getPayload(); - String value = timeInfo.toUpperCase(); - - logger.info("Timer is triggered with TimeInfo: " + value); - - // (Optionally) access and use the Azure function context. - ExecutionContext context = (ExecutionContext) message.getHeaders().get(UppercaseHandler.EXECUTION_CONTEXT); - context.getLogger().info("Execution Context Log - TimeInfo: " + value); - - // No response. - }; - } ----- - -TIP: The uppercase function does not return value (e.g. Void output type) and is backed by `java.util.Consumer`. - -The `UppercaseHandler` (marked as Spring `@Component`) implements the Azure function using the Azure Function Java API. Furthermore as Spring component the UppercaseHandler leverages the Spring configuration and programming model to inject the necessary services required by the functions. - -[source,java] ----- -@Component -public class UppercaseHandler { - - public static String EXECUTION_CONTEXT = "executionContext"; - - @Autowired - private Consumer> uppercase; - - @FunctionName("uppercase") - public void execute(@TimerTrigger(name = "keepAliveTrigger", schedule = "0 */1 * * * *") String timerInfo, - ExecutionContext context) { - - Message message = MessageBuilder - .withPayload(timerInfo) - .setHeader(EXECUTION_CONTEXT, context) - .build(); - - this.uppercase.accept(message); - } -} ----- - -=== Notes - -- Change the `spring-boot-maven-plugin` to `tiny` in favor of the `azure-functions-maven-plugin` jar packaging. -- Add `"AzureWebJobsStorage": "UseDevelopmentStorage=true"` to the `local.settings.json`. diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw b/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw deleted file mode 100755 index 8a8fb2282..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`\\unset -f command; \\command -v java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw.cmd b/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw.cmd deleted file mode 100644 index 1d8ab018e..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/mvnw.cmd +++ /dev/null @@ -1,188 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml b/spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml deleted file mode 100644 index dd6487a6e..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - com.example.azure.di - azure-timetrigger-demo - 0.0.1-SNAPSHOT - azure-timetrigger-demo - Demo project for Spring Boot - - 17 - 1.0.28.RELEASE - - - com.example.azure.di.timetriggerdemo.TimeTriggerDemoApplication - - - 1.22.0 - spring-cloud-function-samples - westus - java-functions-group - java-functions-app-service-plan - EP1 - - - - - org.springframework.cloud - spring-cloud-function-adapter-azure - 4.1.0-SNAPSHOT - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - - ${functionAppName} - ${functionResourceGroup} - ${functionAppRegion} - ${functionAppServicePlanName} - ${functionPricingTier} - - ${project.basedir}/src/main/resources/host.json - ${project.basedir}/src/main/resources/local.settings.json - - - linux - 17 - - - 7072 - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${spring-boot-thin-layout.version} - - - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/TimeTriggerDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/TimeTriggerDemoApplication.java deleted file mode 100644 index e3e10ddc8..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/TimeTriggerDemoApplication.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.timetriggerdemo; - -import java.util.function.Consumer; - -import com.microsoft.azure.functions.ExecutionContext; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; - -@SpringBootApplication -public class TimeTriggerDemoApplication { - - private static Log logger = LogFactory.getLog(TimeTriggerDemoApplication.class); - - public static void main(String[] args) { - SpringApplication.run(TimeTriggerDemoApplication.class, args); - } - - @Bean - public Consumer> uppercase() { - return message -> { - String timeInfo = message.getPayload(); - String value = timeInfo.toUpperCase(); - - logger.info("Timer is triggered with TimeInfo: " + value); - - // (Optionally) access and use the Azure function context. - ExecutionContext context = (ExecutionContext) message.getHeaders().get(UppercaseHandler.EXECUTION_CONTEXT); - context.getLogger().info("Execution Context Log - TimeInfo: " + value); - - // No response. - }; - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/UppercaseHandler.java b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/UppercaseHandler.java deleted file mode 100644 index ca3890206..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/java/com/example/azure/di/timetriggerdemo/UppercaseHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2021-2022 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 com.example.azure.di.timetriggerdemo; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.annotation.ExponentialBackoffRetry; -import com.microsoft.azure.functions.annotation.FixedDelayRetry; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.TimerTrigger; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; - -@Component -public class UppercaseHandler { - - public static String EXECUTION_CONTEXT = "executionContext"; - - private static AtomicInteger count = new AtomicInteger(); - - @Autowired - private Consumer> uppercase; - - @FunctionName("uppercase") - @FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10") - public void execute(@TimerTrigger(name = "keepAliveTrigger", schedule = "0 */1 * * * *") String timerInfo, - ExecutionContext context) { - - Message message = MessageBuilder - .withPayload(timerInfo) - .setHeader(EXECUTION_CONTEXT, context) - .build(); - - this.uppercase.accept(message); - } - - @FunctionName("uppercaseExpRetry") - @ExponentialBackoffRetry(maxRetryCount = 4, maximumInterval = "00:15:00", minimumInterval = "00:00:03") - public void executeExpRetry(@TimerTrigger(name = "keepAliveTrigger", schedule = "*/10 * * * * *") String timerInfo, - ExecutionContext context) { - - if (count.incrementAndGet() < 3) { - context.getLogger().info("EMULATE ERROR# " + count.get()); - throw new IllegalStateException("Emulated ERROR# " + count.get()); - } - - context.getLogger().info("ERRORLESS EXECUTION"); - - Message message = MessageBuilder - .withPayload(timerInfo) - .setHeader(EXECUTION_CONTEXT, context) - .build(); - - this.uppercase.accept(message); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/host.json b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/host.json deleted file mode 100644 index 10d0c0748..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/host.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.*, 4.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/local.settings.json b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/local.settings.json deleted file mode 100644 index adce8b884..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/main/resources/local.settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "AzureWebJobsDashboard": "", - "FUNCTIONS_WORKER_RUNTIME": "java" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/test/java/com/example/azure/di/timetriggerdemo/TimetriggerDemoApplicationTests.java b/spring-cloud-function-samples/function-sample-azure-time-trigger/src/test/java/com/example/azure/di/timetriggerdemo/TimetriggerDemoApplicationTests.java deleted file mode 100644 index d78399a12..000000000 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/src/test/java/com/example/azure/di/timetriggerdemo/TimetriggerDemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.azure.di.timetriggerdemo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class TimetriggerDemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-web/.gitignore b/spring-cloud-function-samples/function-sample-azure-web/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index cb28b0e37c7d206feb564310fdeec0927af4123a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62547 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 A?*IS* diff --git a/spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 462686e25..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/spring-cloud-function-samples/function-sample-azure-web/README.adoc b/spring-cloud-function-samples/function-sample-azure-web/README.adoc deleted file mode 100644 index a1da540de..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/README.adoc +++ /dev/null @@ -1,66 +0,0 @@ -== Spring Azure Web Adapter Demo - -A https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-adapters/spring-cloud-function-adapter-azure-web[spring-cloud-function-adapter-azure-web] adapter sample. - -This sample implements a standard Spring Boot Web application, with a REST API for managing a list of country entities. Later are persisted with JPA and H2 database. - -The `spring-cloud-function-adapter-azure-web` adapter provides a light-weight Azure Function forwarding proxy which allows deploying the existing Spring Boot Web application as a Azure Function. - -=== Usage - -==== Build - -[source,shell] ----- -./mvnw clean install ----- - -==== Run Locally - -[source,shell] ----- -./mvnw azure-functions:run ----- - -Then use `curl` to interact with the rest application: - ----- -curl -X GET http://localhost:7072/api/AzureWebAdapter/ ----- - -will output result like `Country Count: 0`. - -Then add few Countries: ----- -curl -X POST -H 'Content-Type:application/json' http://localhost:7072/api/AzureWebAdapter/countries -d '{"name" : "Bulgaria"}' -curl -X POST -H 'Content-Type:application/json' http://localhost:7072/api/AzureWebAdapter/countries -d '{"name" : "Netherlands"}' -curl -X POST -H 'Content-Type:application/json' http://localhost:7072/api/AzureWebAdapter/countries -d '{"name" : "Ukraine"}' ----- - -And check the count again: - ----- -curl -X GET http://localhost:7072/api/AzureWebAdapter/ ----- - -now the output is `Country Count: 3` and `curl -X GET http://localhost:7072/api/AzureWebAdapter/countries` will output: `Countries: Country{id=1, name='Bulgaria'}Country{id=2, name='Netherlands'}Country{id=3, name='Ukraine'}`. - -==== Running on Azure - -Make sure you are logged in your Azure account. - ----- -az login ----- - -and deploy - ----- -./mvnw azure-functions:deploy ----- - - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-web/mvnw b/spring-cloud-function-samples/function-sample-azure-web/mvnw deleted file mode 100755 index 66df28542..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/mvnw +++ /dev/null @@ -1,308 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.2.0 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "$(uname)" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home"; export JAVA_HOME - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && - JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin ; then - javaHome="$(dirname "\"$javaExecutable\"")" - javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "\"$javaExecutable\"")" - fi - javaHome="$(dirname "\"$javaExecutable\"")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$(cd "$wdir/.." || exit 1; pwd) - fi - # end of workaround - done - printf '%s' "$(cd "$basedir" || exit 1; pwd)" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' < "$1" - fi -} - -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi -} - -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" -else - log "Couldn't find $wrapperJarPath, downloading it ..." - - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; - esac - done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" - - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi - - if command -v wget > /dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; - esac -done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - elif command -v shasum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." - exit 1 - fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 - exit 1 - fi -fi - -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-azure-web/mvnw.cmd b/spring-cloud-function-samples/function-sample-azure-web/mvnw.cmd deleted file mode 100644 index 95ba6f54a..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/mvnw.cmd +++ /dev/null @@ -1,205 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-azure-web/pom.xml b/spring-cloud-function-samples/function-sample-azure-web/pom.xml deleted file mode 100644 index 7b733f747..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/pom.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - com.example - azure-web-demo - 0.0.1-SNAPSHOT - azure-web-demo - Spring Cloud Function - Azure Function Web Adapter Demo - - - - 17 - - 1.0.28.RELEASE - 4.1.0-SNAPSHOT - - - com.example.azure.web.AzureWebDemoApplication - - - 1.22.0 - scf-azure-web-sample - westus - java-functions-group - java-functions-app-service-plan - EP1 - - - - - - - - org.springframework.cloud - spring-cloud-function-adapter-azure-web - ${spring-cloud-function-adapter-azure-web.version} - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - - org.springframework.boot - spring-boot-starter-validation - - - - com.h2database - h2 - runtime - - - - org.springframework.boot - spring-boot-starter-actuator - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - - ${functionAppName} - ${functionResourceGroup} - ${functionAppRegion} - ${functionAppServicePlanName} - ${functionPricingTier} - - ${project.basedir}/src/main/resources/host.json - - - linux - 17 - - - 7072 - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${spring-boot-thin-layout.version} - - - - - - - - - - spring-snapshot - https://repo.spring.io/snapshot - - true - - - false - - - - spring-milestone - https://repo.spring.io/milestone - - - - diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/AzureWebDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/AzureWebDemoApplication.java deleted file mode 100644 index c2e09a03b..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/AzureWebDemoApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.azure.web; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; - -@SpringBootApplication -@EnableJpaRepositories -public class AzureWebDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(AzureWebDemoApplication.class, args); - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/Country.java b/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/Country.java deleted file mode 100644 index 2fbecb4bd..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/Country.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2023-2023 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 com.example.azure.web; - -import java.util.Objects; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -/** - * - * @author Christian Tzolov - */ - -@Table(name = "COUNTRIES") -@Entity -public class Country { - - @Id - @GeneratedValue - private Long id; - - private String name; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - Country country = (Country) o; - return id == country.id && name.equals(country.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } - - @Override - public String toString() { - return "Country{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryController.java b/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryController.java deleted file mode 100644 index f6d16f918..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2023-2023 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 com.example.azure.web; - -import java.util.stream.Collectors; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * - * @author Christian Tzolov - */ -@RestController -public class CountryController { - - @Autowired - private CountryRepository countryRepository; - - @GetMapping("/") - public String index() { - return "Country Count: " + countryRepository.count(); - } - - @GetMapping("/countries") - public String allCountries() { - String countries = this.countryRepository.findAll().stream() - .map(country -> country.toString()) - .collect(Collectors.joining()); - - return "Countries: " + countries; - } - - @PostMapping(path = "/countries") - public Country addCountry(@RequestBody Country country) { - if (!StringUtils.hasText(country.getName())) { - return null; - } - return this.countryRepository.save(country); - } - - @GetMapping("/countries/{id}") - public Country countryById(@PathVariable Integer id) { - return this.countryRepository.findById(id).get(); - } -} diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryRepository.java b/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryRepository.java deleted file mode 100644 index 3f08e010b..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/java/com/example/azure/web/CountryRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2023-2023 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 com.example.azure.web; - -import org.springframework.data.jpa.repository.JpaRepository; - -/** - * - * @author Christian Tzolov - */ -public interface CountryRepository extends JpaRepository { -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/application.properties deleted file mode 100644 index 2226f0b85..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/application.properties +++ /dev/null @@ -1,6 +0,0 @@ -spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.jpa.defer-datasource-initialization=true \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/host.json b/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/host.json deleted file mode 100644 index 10d0c0748..000000000 --- a/spring-cloud-function-samples/function-sample-azure-web/src/main/resources/host.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.*, 4.0.0)" - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure/.gitignore b/spring-cloud-function-samples/function-sample-azure/.gitignore deleted file mode 100644 index c7f1c2e74..000000000 --- a/spring-cloud-function-samples/function-sample-azure/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -extensions.csproj -obj/ -lib/ - diff --git a/spring-cloud-function-samples/function-sample-azure/Dockerfile b/spring-cloud-function-samples/function-sample-azure/Dockerfile deleted file mode 100644 index b8d1c0b63..000000000 --- a/spring-cloud-function-samples/function-sample-azure/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM springcloudstream/azure-functions-java17:1.0.0 - -COPY ./target/azure-functions /src/java-function-app - -RUN mkdir -p /home/site/wwwroot && \ - cd /src/java-function-app && \ - cd $(ls -d */|head -n 1) && \ - cp -a . /home/site/wwwroot - -ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ - AzureFunctionsJobHost__Logging__Console__IsEnabled=true diff --git a/spring-cloud-function-samples/function-sample-azure/README.adoc b/spring-cloud-function-samples/function-sample-azure/README.adoc deleted file mode 100644 index f9812e70d..000000000 --- a/spring-cloud-function-samples/function-sample-azure/README.adoc +++ /dev/null @@ -1,507 +0,0 @@ -== (Legacy) FunctionInvoker Integration - -WARNING: The legacy `FunctionInvoker` programming model is deprecated and will not be supported going forward. -For up to date samples, aligned with the dependency-injections https://docs.spring.io/spring-cloud-function/docs/current/reference/html/azure.html#_microsoft_azure[Azure Adapter], check the: https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-blob-trigger[Blob Trigger], https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-http-trigger[HTTP Trigger], https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-timer-trigger[Timer Trigger], https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-kafka-trigger[ Kafka Trigger & Output Binding]. -For a Gradle project example check the https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle[ HTTP Trigger with Gradle]. - -=== Overview -The https://azure.microsoft.com[Azure] adapter bootstraps a Spring Cloud Function context and channels function calls from the Azure -framework into the user functions, using Spring Boot configuration where necessary. Azure Functions has quite a unique and -invasive programming model, involving annotations in user code that are specific to the Azure platform. -However, it is important to understand that because of the style of integration provided by Spring Cloud Function, specifically `org.springframework.cloud.function.adapter.azure.FunctionInvoker`, this annotation-based programming model is simply a type-safe way to configure -your simple java function (function that has no awareness of Azure) to be recognized as Azure function. -All you need to do is create a handler that extends `FunctionInvoker`, define and configure your function handler method and -make a callback to `handleRequest(..)` method. This handler method provides input and output types as annotated method parameters -(enabling Azure to inspect the class and create JSON bindings). - - -[source,java] ----- -public class UppercaseHandler extends FunctionInvoker, String> { - - @FunctionName("uppercase") - public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET, - HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - Message message = MessageBuilder.withPayload(request.getBody().get()).copyHeaders(request.getHeaders()).build(); - return handleRequest(message, context); - } -} ----- - -Note that aside form providing configuration via Azure annotation we create an instance of `Message` inside the body of this handler method and make a callback to `handleRequest(..)` method returning its result. - -The actual user function you're delegating to looks like this - -[source,java] ----- -@Bean -public Function uppercase() { - return payload -> payload.toUpperCase(); -} - -OR - -@Bean -public Function, String> uppercase() { - return message -> message.getPayload().toUpperCase(); -} ----- - -Note that when creating a Message you can copy HTTP headers effectively making them available to you if necessary. - -The `org.springframework.cloud.function.adapter.azure.FunctionInvoker` class has two useful -methods (`handleRequest` and `handleOutput`) to which you can delegate the actual function call, so mostly the function will only ever have one line. - -The function name (definition) will be retrieved from Azure's `ExecutionContext.getFunctionName()` method, effectively supporting multiple function in the application context. - -==== Accessing Azure ExecutionContext - -Some time there is a need to access the target execution context provided by the Azure runtime in the form of `com.microsoft.azure.functions.ExecutionContext`. -For example one of such needs is logging, so it can appear in the Azure console. - -For that purpose the FunctionInvoker will add an instance of the `ExecutionContext` as a Message header so you can retrieve it via `executionContext` key. - -``` -@Bean -public Function, String> uppercase(JsonMapper mapper) { - return message -> { - String value = message.getPayload(); - ExecutionContext context = (ExecutionContext) message.getHeaders().get("executionContext"); - . . . - } -} -``` - -==== Notes on JAR Layout - -You don't need the Spring Cloud Function Web at runtime in Azure, so you can exclude this -before you create the JAR you deploy to Azure, but it won't be used if you include it, so -it doesn't hurt to leave it in. A function application on Azure is an archive generated by - the Maven plugin. The function lives in the JAR file generated by this project. - The sample creates it as an executable jar, using the thin layout, so that Azure can find - the handler classes. If you prefer you can just use a regular flat JAR file. - The dependencies should *not* be included. - -==== Build file setup - -In order to run Spring Cloud Function applications on Microsoft Azure, you can leverage the Maven -plugin offered by the cloud platform provider. - -In order to use the adapter plugin for Maven, add the plugin dependency to your `pom.xml` -file: - -[source,xml] ----- - - - org.springframework.cloud - spring-cloud-function-adapter-azure - - ----- - -Then, configure the plugin. You will need to provide Azure-specific configuration for your -application, specifying the `resourceGroup`, `appName` and other optional properties, and - add the `package` goal execution so that the `function.json` file required by Azure is - generated for you. Full plugin documentation can be found in the https://github.com/microsoft/azure-maven-plugins[plugin repository]. - -[source,xml] ----- - - com.microsoft.azure - azure-functions-maven-plugin - - ${functionResourceGroup} - ${functionAppName} - - - - package-functions - - package - - - - ----- - -You will also have to ensure that the files to be scanned by the plugin can be found in the -Azure functions staging directory (see the https://github.com/microsoft/azure-maven-plugins[plugin repository] - for more details on the staging directory and it's default location). - -You can find the entire sample `pom.xml` file for deploying Spring Cloud Function -applications to Microsoft Azure with Maven https://github.com/spring-cloud/spring-cloud-function/blob/{branch}/spring-cloud-function-samples/function-sample-azure/pom.xml[here]. - -NOTE: As of yet, only Maven plugin is available. Gradle plugin has not been created by -the cloud platform provider. - -==== Build - ----- -./mvnw -U clean package ----- - -==== Running the sample - -You can run the sample locally, just like the other Spring Cloud Function samples: - ---- -./mvnw spring-boot:run ---- - -and `curl -H "Content-Type: text/plain" localhost:8080/api/uppercase -d '{"value": "hello foobar"}'`. - -You will need the `az` CLI app (see https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven for more detail). To deploy the function on Azure runtime: - ----- -$ az login -$ mvn azure-functions:deploy ----- - -On another terminal try this: `curl https:///api/uppercase -d '{"value": "hello foobar!"}'`. Please ensure that you use the right URL for the function above. Alternatively you can test the function in the Azure Dashboard UI (click on the function name, go to the right hand side and click "Test" and to the bottom right, "Run"). - -The input type for the function in the Azure sample is a Foo with a single property called "value". So you need this to test it with something like below: - ----- -{ - "value": "foobar" -} ----- - -NOTE: The Azure sample app is written in the "non-functional" style (using `@Bean`). The functional style (with just `Function` or `ApplicationContextInitializer`) is much faster on startup in Azure than the traditional `@Bean` style, so if you don't need `@Beans` (or `@EnableAutoConfiguration`) it's a good choice. Warm starts are not affected. - - -== Running Sample Locally -You can run this Azure function locally, similar to other Spring Cloud Function samples, however -this time by using the Azure Maven plugin, as the Microsoft Azure functions execution context must be available. - -NOTE: To run locally on top of Azure Functions, and to deploy to your live Azure environment, you will need the Azure Functions Core Tools installed along with the Azure CLI (see https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment[here] for details). - -.Follow these steps to build and run locally: -[source,bash] ----- -../../mvnw clean package -../../mvnw azure-functions:run ----- -.console output -[source,bash] ----- -[INFO] Azure Function App's staging directory found at: /Users/cbono/repos/spring-cloud-function/spring-cloud-function-samples/function-sample-azure/target/azure-functions/spring-cloud-function-samples -4.0.3971 -[INFO] Azure Functions Core Tools found. - -Azure Functions Core Tools -Core Tools Version: 4.0.3971 Commit hash: d0775d487c93ebd49e9c1166d5c3c01f3c76eaaf (64-bit) -Function Runtime Version: 4.0.1.16815 - -info: Microsoft.AspNetCore.Hosting.Diagnostics[1] - Request starting HTTP/2 POST http://127.0.0.1:53836/AzureFunctionsRpcMessages.FunctionRpc/EventStream application/grpc - -info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] - Executing endpoint 'gRPC - /AzureFunctionsRpcMessages.FunctionRpc/EventStream' -[2022-04-11T03:04:05.143Z] OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release. -[2022-04-11T03:04:05.247Z] Worker process started and initialized. - -Functions: - - echo: [GET,POST] http://localhost:7071/api/echo - - echoStream: [GET,POST] http://localhost:7071/api/echoStream - - uppercase: [GET,POST] http://localhost:7071/api/uppercase - - uppercaseReactive: [GET,POST] http://localhost:7071/api/uppercaseReactive - -For detailed output, run func with --verbose flag. -[2022-04-11T03:04:10.163Z] Host lock lease acquired by instance ID '000000000000000000000000BEFE21CF'. - ----- - -.Test the _uppercase_ function using the following _curl_ command: -[source,bash] ----- -curl -H "Content-Type: application/json" localhost:7071/api/uppercase -d '{"greeting": "hello", "name": "foo"}' ----- -.curl response -[source,json] ----- -{ - "greeting": "HELLO", - "name": "FOO" -} ----- -Notice that the URL is of the format `/api/`). - -The `uppercase` function signature is `Function, String> uppercase()`. The implementation of `UppercaseHandler` (which extends `FunctionInvoker`) copies the HTTP headers of the incoming request into the input message's _MessageHeaders_ which makes them accessible to the function if needed. - -NOTE: Implementation of `FunctionInvoker` (your handler), should contain the least amount of code. It is really a type-safe way to define -and configure function to be recognized as Azure Function. -Everything else should be delegated to the base `FunctionInvoker` via `handleRequest(..)` callback which will invoke your function, taking care of -necessary type conversion, transformation etc. One exception to this rule is when custom result handling is required. In that case, the proper post-process method can be overridden as well in order to take control of the results processing. - -.UppercaseHandler.java -[source,java] ----- -@FunctionName("uppercase") -public String execute( - @HttpTrigger( - name = "req", - methods = {HttpMethod.GET, HttpMethod.POST}, - authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context -) { - Message message = MessageBuilder.withPayload(request.getBody().get()) - .copyHeaders(request.getHeaders()).build(); - return handleRequest(message, context); -} ----- - - -The `echo` function does the same as the `uppercase` less the actual uppercasing. However, the important difference to notice is that function itself -takes primitive `String` as its input (i.e., `public Function echo()`) while the actual handler passes instance of `Message` the same way as with `uppercase`. The framework recognizes that you only care about the payload and extracts it from the `Message` before calling the function. - -There is also a reactive version of _uppercase_ (named _uppercaseReactive_) which will produce the same result, but -demonstrates and validates the ability to use reactive functions with Azure. - -== Running on Azure - -NOTE: The Azure Java functions runtime does not yet support Java 17 but Spring Cloud Function 4.x requires it. To get around this limitation we deploy to Azure in a custom Docker container. Once https://github.com/Azure/azure-functions-java-worker/issues/548[Azure supports] Java 17 we can move back to using non-Docker deployments. - -==== Custom Docker Image -The steps below describe the process to create a custom Docker image which is suitable for deployment on Azure and contains the 4.x Azure Functions runtime, the MS Java 17 JVM, and the sample functions in this repo. - -====== Image name -Pick an image name for the Docker container (eg. `onobc/function-sample-azure-java17:1.0.0`) and update the _pom.xml_ `functionDockerImageName` property with the image name. - -TIP: By default it is expected that the image name is a publicly accessible image on Docker Hub. However, other registries and credentials can be configured as described https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supporte-runtime[here]. - -.Rebuild the functions (pom.xml was updated): -[source,bash] ----- -../../mvnw clean package ----- -.Build the Docker image: -[source,bash] ----- -docker build -t . ----- - -Test the Docker image locally by starting the container and issuing a request. - -.Start the function runtime locally in Docker: -[source,bash] ----- -docker run -p 8080:80 ----- - -.console output -[source,bash] ----- -cbono@cbono-a01 function-sample-azure % docker run -p 8080:80 onobc/function-sample-azure-java17:1.0.0 -info: Host.Triggers.Warmup[0] - Initializing Warmup Extension. -info: Host.Startup[503] - Initializing Host. OperationId: 'e7317c18-4daa-4d69-bf38-beaa51e1a012'. -info: Host.Startup[504] - Host initialization: ConsecutiveErrors=0, StartupCount=1, OperationId=e7317c18-4daa-4d69-bf38-beaa51e1a012 -info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0] - LoggerFilterOptions - { - "MinLevel": "None", - "Rules": [ - { - "ProviderName": null, - "CategoryName": null, - "LogLevel": null, - "Filter": "b__0" - }, - { - "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider", - "CategoryName": null, - "LogLevel": "None", - "Filter": null - }, - { - "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider", - "CategoryName": null, - "LogLevel": null, - "Filter": "b__0" - } - ] - } -... -... -... -info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0] - Initializing function HTTP routes - Mapped function route 'api/echo' [GET,POST] to 'echo' - Mapped function route 'api/echoStream' [GET,POST] to 'echoStream' - Mapped function route 'api/uppercase' [GET,POST] to 'uppercase' - Mapped function route 'api/uppercaseReactive' [GET,POST] to 'uppercaseReactive' - -info: Host.Startup[412] - Host initialized (65ms) -info: Host.Startup[413] - Host started (81ms) -info: Host.Startup[0] - Job host started -Hosting environment: Production -Content root path: /azure-functions-host -Now listening on: http://[::]:80 -Application started. Press Ctrl+C to shut down. -info: Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcFunctionInvocationDispatcher[0] - Worker process started and initialized. -info: Host.General[337] - Host lock lease acquired by instance ID '000000000000000000000000C4043012'. ----- - -.Test the _uppercase_ function using the following _curl_ command: -[source,bash] ----- -curl -H "Content-Type: application/json" localhost:8080/api/uppercase -d '{"greeting": "hello", "name": "foo"}' ----- -.curl response -[source,json] ----- -{ - "greeting": "HELLO", - "name": "FOO" -} ----- - -.Push the image to Docker registry: -[source,bash] ----- -docker push ----- -At this point the custom image has been created and pushed to the configured Docker registry. - -==== Deploy to Azure -To deploy the functions to your live Azure environment, including automatic provisioning of an _HTTPTrigger_ for each function, do the following. - -.Login to Azure: -[source,bash] ----- -az login ----- - -.Deploy to Azure: -[source,bash] ----- -../../mvnw azure-functions:deploy ----- -.console output -[source,bash] ----- -[INFO] ---------------< io.spring.sample:function-sample-azure >--------------- -[INFO] Building function-sample-azure 4.0.0.RELEASE -[INFO] --------------------------------[ jar ]--------------------------------- -[INFO] -[INFO] --- azure-functions-maven-plugin:1.16.0:deploy (default-cli) @ function-sample-azure --- -Auth type: AZURE_CLI -Default subscription: SCDF-Azure(b80d18******) -Username: cbono@vmware.com -[INFO] Subscription: SCDF-Azure(*******) -[INFO] Reflections took 123 ms to scan 6 urls, producing 24 keys and 486 values -[INFO] Start creating Resource Group(java-functions-group) in region (West US)... -[INFO] Resource Group(java-functions-group) is successfully created. -[INFO] Reflections took 1 ms to scan 3 urls, producing 12 keys and 12 values -[INFO] Creating app service plan java-functions-app-service-plan... -[INFO] Successfully created app service plan java-functions-app-service-plan. -[INFO] Start creating Application Insight (spring-cloud-function-samples)... -[INFO] Application Insight (spring-cloud-function-samples) is successfully created. You can visit https://ms.portal.azure.com/********providers/Microsoft.Insights/components/spring-cloud-function-samples to view your Application Insights component. -[INFO] Creating function app spring-cloud-function-samples... -[INFO] Set function worker runtime to java. -[INFO] Ignoring decoding of null or empty value to:com.azure.resourcemanager.storage.fluent.models.StorageAccountInner -[INFO] Successfully created function app spring-cloud-function-samples. -[INFO] Skip deployment for docker app service -[INFO] ------------------------------------------------------------------------ -[INFO] BUILD SUCCESS -[INFO] ------------------------------------------------------------------------ -[INFO] Total time: 01:30 min -[INFO] Finished at: 2022-04-04T19:06:24-05:00 -[INFO] ------------------------------------------------------------------------ ----- - -TIP: When deployed as a Docker container the function urls are not written to the console. You will need to inspect the functions in the Azure Portal to find the urls. - -==== Inspect in Azure Portal - -Navigate to the https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.Web%2Fsites/kind/functionapp[Function App] dashboard in the Azure portal and then: - -* click on your function app (`"spring-cloud-function-samples"` by default) -* click the left nav `"Functions"` link -* click the `"uppercase"` function - -====== Function Url -Click the `"Get Function Url"` link to see the function's url. - -====== Test via Portal -* click on the left nav `"Code and Test"` -* click on `"Test/Run"` at top of page -* enter the following input json in the `"Body"` section on the right-hand side: - -[source,json] ----- -{ - "greeting": "hello", - "name": "foo" -} ----- -* click "Run" and the output should look like: - -[source,json] ----- -{ - "greeting": "HELLO", - "name": "FOO" -} ----- - -===== Test via cURL -Armed w/ the function url from above, issue the following curl command in another terminal: - -[source,bash] ----- -curl -H "Content-Type: application/json" https://spring-cloud-function-samples.azurewebsites.net/api/uppercase -d '{"greeting": "hello", "name": "foo"}' ----- -.curl response -[source,json] ----- -{ - "greeting": "HELLO", - "name": "FOO" -} ----- - -TIP: The Azure dashboard provides a plethora of information about your functions, including but not limited to execution count, memory consumption and execution time. - - -==== Custom Result Handling - -As noted above, the implementation of `FunctionInvoker` (your handler), should contain the least amount of code possible. However, if custom result handling needs to occur there is a set of methods (named `postProcess**`) that can be overridden in link:../../spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/FunctionInvoker.java[FunctionInvoker.java]. - -One such example can be seen in link:src/main/java/example/ReactiveEchoCustomResultHandler.java[ReactiveEchoCustomResultHandler.java]. - -Once the function is deployed it can be tested using _curl_: - -[source,bash] ----- -curl -H "Content-Type: application/json" localhost:7071/api/echoStream -d '["hello","peepz"]' ----- -.result -[source,bash] ----- -Kicked off job for [hello, peepz] ----- -The custom result handling takes the Flux returned from the `echoStream` function and adds logging, uppercase mapping, and then subscribes to the publisher. The Azure logs output the following: - -[source,bash] ----- -[2022-03-01T01:36:57.439Z] 2022-02-28 19:36:57.439 INFO 20587 --- [pool-2-thread-2] o.s.boot.SpringApplication : Started application in 0.466 seconds (JVM running for 57.906) -[2022-03-01T01:36:57.462Z] BEGIN echo post-processing work ... -[2022-03-01T01:36:57.462Z] HELLO -[2022-03-01T01:36:57.462Z] PEEPZ -[2022-03-01T01:36:57.463Z] END echo post-processing work -[2022-03-01T01:36:57.463Z] Function "echoStream" (Id: 678cff0b-d958-4fab-967b-e19e0d5d67e8) invoked by Java Worker ----- diff --git a/spring-cloud-function-samples/function-sample-azure/pom.xml b/spring-cloud-function-samples/function-sample-azure/pom.xml deleted file mode 100644 index bd9376697..000000000 --- a/spring-cloud-function-samples/function-sample-azure/pom.xml +++ /dev/null @@ -1,266 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-azure - 0.0.1-SNAPSHOT - jar - - function-sample-azure - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - spring-cloud-function-samples - westus - java-functions-group - java-functions-app-service-plan - onobc/function-sample-azure-java17:1.0.0 - ${project.build.directory}/azure-functions/${functionAppName} - example.Config - 1.21.0 - 2.1.0 - 1.0.27.RELEASE - 17 - UTF-8 - - - - - org.springframework.cloud - spring-cloud-function-adapter-azure - 4.1.0-SNAPSHOT - - - org.springframework.cloud - spring-cloud-starter-function-web - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - 4.1.0-SNAPSHOT - pom - import - - - com.microsoft.azure.functions - azure-functions-java-library - ${azure.functions.java.library.version} - - - - - - - - - org.apache.maven.plugins - maven-clean-plugin - - - - ${basedir} - - obj/** - - - - ${basedir} - - extensions.csproj - - - - - - - com.microsoft.azure - azure-functions-maven-plugin - ${azure.functions.maven.plugin.version} - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${stagingDirectory}/lib - false - false - true - runtime - azure-functions-java-library - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - ${project.build.sourceEncoding} - - - - com.microsoft.azure - azure-functions-maven-plugin - - ${functionResourceGroup} - ${functionAppName} - ${functionAppRegion} - ${functionAppServicePlanName} - EP1 - - - linux - 17 - - - - - FUNCTIONS_EXTENSION_VERSION - ~4 - - - - - - package-functions - - package - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - true - - ${stagingDirectory} - - - - ${project.basedir}/src/main/azure - - - ** - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - - - - - - 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 - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/azure/host.json b/spring-cloud-function-samples/function-sample-azure/src/main/azure/host.json deleted file mode 100644 index cfb16c7ce..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/azure/host.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "functionTimeout": "00:05:00", - "version": "2.0" -} diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json b/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json deleted file mode 100644 index 3470fde9a..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "AzureWebJobsStorage": "", - "AzureWebJobsDashboard": "", - "FUNCTIONS_WORKER_RUNTIME": "java" - } -} diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/Config.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/Config.java deleted file mode 100644 index b40249436..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/Config.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2022 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 java.util.Map; -import java.util.function.Function; - -import com.microsoft.azure.functions.ExecutionContext; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; - -/** - * @author Oleg Zhurakousky - * @author Chris Bono - */ -@SpringBootApplication -public class Config { - - public static void main(String[] args) throws Exception { - SpringApplication.run(Config.class, args); - } - - @Bean - public Function echo() { - return payload -> payload; - } - - @Bean - public Function, String> uppercase(JsonMapper mapper) { - return message -> { - String value = message.getPayload(); - ExecutionContext context = (ExecutionContext) message.getHeaders().get("executionContext"); - try { - Map map = mapper.fromJson(value, Map.class); - - if(map != null) - map.forEach((k, v) -> map.put(k, v != null ? v.toUpperCase() : null)); - - if(context != null) - context.getLogger().info(new StringBuilder().append("Function: ") - .append(context.getFunctionName()).append(" is uppercasing ").append(value.toString()).toString()); - - return mapper.toString(map); - } catch (Exception e) { - e.printStackTrace(); - if(context != null) - context.getLogger().severe("Function could not parse incoming request"); - - return ("Function error: - bad request"); - } - }; - } - - @Bean - public Function, Mono> uppercaseReactive() { - return mono -> mono.map(value -> value.toUpperCase()); - } - - @Bean - public Function, Flux> echoStream() { - return flux -> flux.map(value -> value.toUpperCase()); - } -} - diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/EchoHandler.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/EchoHandler.java deleted file mode 100644 index 784f0e86c..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/EchoHandler.java +++ /dev/null @@ -1,46 +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 com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; - -import java.util.Optional; - -import org.springframework.cloud.function.adapter.azure.FunctionInvoker; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @author Soby Chacko - * @author Oleg Zhurakousky - */ -public class EchoHandler extends FunctionInvoker, String> { - - @FunctionName("echo") - public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET, - HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - Message message = MessageBuilder.withPayload(request.getBody().get()).copyHeaders(request.getHeaders()).build(); - return handleRequest(message, context); - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveEchoCustomResultHandler.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveEchoCustomResultHandler.java deleted file mode 100644 index 8f72a80bc..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveEchoCustomResultHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022-2022 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 java.util.List; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.adapter.azure.FunctionInvoker; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; - -/** - * Sample that shows how to customize the default function result handling by operating on the {@link Flux} returned - * from the {@link Config#echoStream()} echoStream} function. - * - * @author Chris Bono - */ -public class ReactiveEchoCustomResultHandler extends FunctionInvoker, String> { - - private static final Log logger = LogFactory.getLog(ReactiveEchoCustomResultHandler.class); - - @FunctionName("echoStream") - public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) - HttpRequestMessage> request, ExecutionContext context - ) { - return handleRequest(request.getBody(), context); - } - - @Override - protected String postProcessFluxFunctionResult(List rawInputs, Object functionInputs, Flux functionResult, - FunctionInvocationWrapper function, ExecutionContext executionContext - ) { - functionResult - .doFirst(() -> executionContext.getLogger().info("BEGIN echo post-processing work ...")) - .mapNotNull((v) -> v.toString().toUpperCase()) - .doFinally((signalType) -> executionContext.getLogger().info("END echo post-processing work")) - .subscribe((v) -> executionContext.getLogger().info(" " + v)); - return "Kicked off job for " + rawInputs; - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveUppercaseHandler.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveUppercaseHandler.java deleted file mode 100644 index cb82087b5..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/ReactiveUppercaseHandler.java +++ /dev/null @@ -1,42 +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 com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; - -import java.util.Optional; - -import org.springframework.cloud.function.adapter.azure.FunctionInvoker; - -/** - * @author Oleg Zhurakousky - */ -public class ReactiveUppercaseHandler extends FunctionInvoker { - - @FunctionName("uppercaseReactive") - public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET, - HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context) { - return handleRequest(request.getBody().get(), context); - } - -} diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/UppercaseHandler.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/UppercaseHandler.java deleted file mode 100644 index 0e342e960..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/UppercaseHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018-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 example; - -import com.microsoft.azure.functions.ExecutionContext; -import com.microsoft.azure.functions.HttpMethod; -import com.microsoft.azure.functions.HttpRequestMessage; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.functions.annotation.FunctionName; -import com.microsoft.azure.functions.annotation.HttpTrigger; - -import java.util.Optional; - -import org.springframework.cloud.function.adapter.azure.FunctionInvoker; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * @author Soby Chacko - * @author Oleg Zhurakousky - */ -public class UppercaseHandler extends FunctionInvoker, String> { - - @FunctionName("uppercase") - public String execute( - @HttpTrigger( - name = "req", - methods = {HttpMethod.GET, HttpMethod.POST}, - authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, - ExecutionContext context - ) { - context.getLogger().warning("Using Java (" + System.getProperty("java.version") + ")"); - Message message = MessageBuilder.withPayload(request.getBody().get()) - .copyHeaders(request.getHeaders()).build(); - return handleRequest(message, context); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.gitignore b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572ce..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/README.adoc b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/README.adoc deleted file mode 100644 index ba154a464..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/README.adoc +++ /dev/null @@ -1,61 +0,0 @@ -## Examples of Cloud Events with Spring via RSocket and Apache Kafka - -### Introduction -The current example uses spring-cloud-function framework as its core which allows users to only worry about functional aspects of -their requirement while taking care-off non-functional aspects. For more information on Spring Cloud Function please visit -our https://spring.io/projects/spring-cloud-function[project page]. - -The example consists of a Spring boot configuration class -https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/DemoApplication.java[DemoApplication] -which contains a sample function which you can interact with following via RSocket and Apache Kafka. - -### From RSocket to Apache Kafka - -While very similar to https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-samples/function-sample-cloudevent-stream[spring-cloud-function-stream] example -there are few interesting variants here worth discussing. -Here we’re introducing a different delivery mechanism. But what really makes it even more interesting is the fact that unlike Apache Kafka or AMQP there is no protocol -binding defined for RSocket. So we will communicate Cloud Event in a structured-mode where the entire event is encoded into some type of structure (e.g., JSON). - -Few implementation details are also defer in this example from the others. However these details are not relevant in any way to Cloud Event, rather -demonstration of other mechanisms you may chose to write your code. For example we’ll be using `Consumer` instead of a `Function` and will be manually -sending an output message using `StreamBridge` component provided by Spring Cloud Stream framework. - -So, here is our application code - -``` -@Bean -public Consumer hire(StreamBridge streamBridge) { - return person -> { - Employee employee = new Employee(person); - streamBridge.send("hire-out-0", CloudEventMessageBuilder.withData(employee) - .setSource("http://spring.io/rsocket") - .setId("1234567890") - .build()); - }; -} -``` -Note how we’re utiliziing CloudEventMessageBuilder to generate output Message as Cloud Event. - -What we will be sending over RSocket is structured representation of Cloud Event: -``` -String payload = "{\n" + - " \"specversion\" : \"1.0\",\n" + - " \"type\" : \"org.springframework\",\n" + - " \"source\" : \"https://spring.io/\",\n" + - " \"id\" : \"A234-1234-1234\",\n" + - " \"datacontenttype\" : \"application/json\",\n" + - " \"data\" : {\n" + - " \"firstName\" : \"John\",\n" + - " \"lastName\" : \"Doe\"\n" + - " }\n" + - "}"; -``` -So, the entire Cloud Event is represented as JSON sent over RSocket to the hire() function. - -``` -rsocketRequesterBuilder.tcp("localhost", 55555) - .route("hire") // target function - .data(payload). // data we're sending - .send() -``` -You can run the demo using https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/test/java/io/spring/cloudevent/DemoApplicationTests.java[DemoApplicationTests] \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw.cmd b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml deleted file mode 100644 index 59bed8335..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/pom.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - 4.0.0 - io.spring.sample - function-sample-cloudevent-rsocket - 0.0.1-SNAPSHOT - function-sample-cloudevent-rsocket - Demo project for Spring Boot - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - - - org.springframework.cloud - spring-cloud-function-rsocket - - - - - - - org.springframework.cloud - spring-cloud-stream-binder-kafka - 4.1.0-SNAPSHOT - - - - io.projectreactor - reactor-test - test - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-surefire-plugin - - - **/*Tests.java - **/*Test.java - - - **/Abstract*.java - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - - diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/DemoApplication.java b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/DemoApplication.java deleted file mode 100644 index a42bf0b79..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/DemoApplication.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.spring.cloudevent; - -import java.util.function.Consumer; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder; -import org.springframework.cloud.stream.function.StreamBridge; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class DemoApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(DemoApplication.class, args); - } - - @Bean - public Consumer hire(StreamBridge streamBridge) { - return person -> { - Employee employee = new Employee(person); - streamBridge.send("hire-out-0", CloudEventMessageBuilder.withData(employee) - .setSource("http://spring.io/rsocket") - .setId("1234567890") - .build()); - }; - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Employee.java b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Employee.java deleted file mode 100644 index e1f04615e..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Employee.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.spring.cloudevent; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Random; - -public class Employee { - - private Person person; - - private int id; - - public Employee() { - - } - - public Employee(Person person) { - this.person = person; - this.id = new Random().nextInt(1000); - } - - public Person getPerson() { - return person; - } - - public void setPerson(Person person) { - this.person = person; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getMessage() { - return "Employee " + id + " was hired on " + new SimpleDateFormat("dd-MM-yyyy").format(new Date()); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Person.java b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Person.java deleted file mode 100644 index 99ded7514..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/java/io/spring/cloudevent/Person.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.spring.cloudevent; - -public class Person { - - private String firstName; - - private String lastName; - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/main/resources/application.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/test/java/io/spring/cloudevent/DemoApplicationTests.java b/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/test/java/io/spring/cloudevent/DemoApplicationTests.java deleted file mode 100644 index 87e232a57..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-rsocket/src/test/java/io/spring/cloudevent/DemoApplicationTests.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.spring.cloudevent; - -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Collections; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.apache.kafka.clients.admin.KafkaAdminClient; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ConditionEvaluationResult; -import org.junit.jupiter.api.extension.ExecutionCondition; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.messaging.Message; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.util.MimeTypeUtils; - - -@SpringBootTest(properties = {"spring.rsocket.server.port=55551"}) -@ExtendWith(DemoApplicationTests.TestRule.class) -public class DemoApplicationTests { - - ArrayBlockingQueue> queue = new ArrayBlockingQueue<>(1000); - - @Autowired - private RSocketRequester.Builder rsocketRequesterBuilder; - - @Test - public void test() throws Exception { - String payload = "{\n" + - " \"specversion\" : \"1.0\",\n" + - " \"type\" : \"org.springframework\",\n" + - " \"source\" : \"https://spring.io/\",\n" + - " \"id\" : \"A234-1234-1234\",\n" + - " \"datacontenttype\" : \"application/json\",\n" + - " \"data\" : {\n" + - " \"firstName\" : \"John\",\n" + - " \"lastName\" : \"Doe\"\n" + - " }\n" + - "}"; - - this.rsocketRequesterBuilder.tcp("localhost", 55551) - .route("hire") - .metadata("{\"content-type\":\"application/cloudevents+json\"}", MimeTypeUtils.APPLICATION_JSON) - .data(payload) - .send() - .subscribe(); - - Message resultFromKafka = queue.poll(2000, TimeUnit.MILLISECONDS); - System.out.println("Result Message: " + resultFromKafka); - System.out.println("Cloud Event 'specversion': " + CloudEventMessageUtils.getSpecVersion(resultFromKafka)); - System.out.println("Cloud Event 'source': " + CloudEventMessageUtils.getSource(resultFromKafka)); - System.out.println("Cloud Event 'id': " + CloudEventMessageUtils.getId(resultFromKafka)); - System.out.println("Cloud Event 'type': " + CloudEventMessageUtils.getType(resultFromKafka)); - } - - @KafkaListener(id = "test", topics = "hire-out-0", clientIdPrefix = "cloudEvents") - public void listen(Message message) { - queue.add(message); - } - - public static class TestRule implements ExecutionCondition { - @Override - public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - try { - Socket socket = new Socket(); - socket.connect(new InetSocketAddress("localhost", 9092)); - socket.close(); - } - catch (Exception e) { - System.out.println("Kafka is not available on localhost:9092"); - return ConditionEvaluationResult.disabled("Kafka is not available on localhost, default port"); - } - - return ConditionEvaluationResult.enabled("All is good"); - } - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.gitignore b/spring-cloud-function-samples/function-sample-cloudevent-sdk/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572ce..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/README.adoc b/spring-cloud-function-samples/function-sample-cloudevent-sdk/README.adoc deleted file mode 100644 index fb2f81bcb..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/README.adoc +++ /dev/null @@ -1,25 +0,0 @@ -## Examples of integration with Cloud-Event SDK - -### Introduction -As described in these two blog posts (https://spring.io/blog/2020/12/10/cloud-events-and-spring-part-1 & https://spring.io/blog/2020/12/23/cloud-events-and-spring-part-2), -Spring natively supports Cloud Event specification so to work with Cloud Events you don't need anything and `function-sample-cloudevent`, `function-sample-cloudevent-rsocket` and `function-sample-cloudevent-stream` examples show exactly how you can benefit from Spring's transparent handling of Cloud Events. - -So this example shows integration of Spring with https://github.com/cloudevents/sdk-java[Cloud Event SDK] (not managed by Spring). - -NOTE: This is only to demonstrate the integration capabilities with Cloud Event SDK (regardless of the reason). It is NOT required to work with Cloud Events. - -In this example the `echo` function uses `CloudEvent` type from java SDK to receive Cloud Event and echo it back using `CloudEventBuilder`. -Note that you also need to register `CloudEventMessageConverter` - - -Simply start the `DemoApplication`. Once started access the `echo` function exposed as an HTTP endpoint - -``` -curl -v -d '{"value": "Foo"}' \ - -H'Content-type: application/json' \ - -H'ce-id: 1' \ - -H'ce-source: function-sample-cloudevent-sdk' \ - -H'ce-type: my.application.Foo' \ - -H'ce-specversion: 1.0' \ - http://localhost:8080/echo -``` \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw b/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw.cmd b/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent-sdk/pom.xml deleted file mode 100644 index 0db1f2d84..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/pom.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - 4.0.0 - io.spring.sample - function-sample-cloudevent-sdk - 0.0.1-SNAPSHOT - function-sample-cloudevent-rsocket - Demo project for Spring Boot - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-web - - - io.cloudevents - cloudevents-spring - 2.3.0 - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-surefire-plugin - - - **/*Tests.java - **/*Test.java - - - **/Abstract*.java - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - - diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/java/io/spring/cloudevent/DemoApplication.java b/spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/java/io/spring/cloudevent/DemoApplication.java deleted file mode 100644 index d7b4822bf..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/java/io/spring/cloudevent/DemoApplication.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.spring.cloudevent; - -import java.net.URI; -import java.util.UUID; -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import io.cloudevents.spring.messaging.CloudEventMessageConverter; - -@SpringBootApplication -public class DemoApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(DemoApplication.class, args); - } - - @Bean - public Function echo() { - return ce -> { - System.out.println("Received: " + ce); - return CloudEventBuilder.from(ce) - .withId(UUID.randomUUID().toString()) - .withSource(URI.create("https://spring.io/foos")) - .withType("io.spring.event.Foo") - .withData(ce.getData().toBytes()) - .build(); - }; - } - - @Bean - public CloudEventMessageConverter cloudEventMessageConverter() { - return new CloudEventMessageConverter(); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-cloudevent-sdk/src/main/resources/application.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/.gitignore b/spring-cloud-function-samples/function-sample-cloudevent-stream/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572ce..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/README.adoc b/spring-cloud-function-samples/function-sample-cloudevent-stream/README.adoc deleted file mode 100644 index 1ca0bad56..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/README.adoc +++ /dev/null @@ -1,54 +0,0 @@ -## Examples of Cloud Events with Spring via AMQP and Apache Kafka - -### Introduction -The current example uses spring-cloud-function framework as its core which allows users to only worry about functional aspects of -their requirement while taking care-off non-functional aspects. For more information on Spring Cloud Function please visit -our https://spring.io/projects/spring-cloud-function[project page]. - -The example consists of a Spring boot configuration class -https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/DemoApplication.java[DemoApplication] -which contains a sample function which you can interact with following via AMQP and Apache Kafka. - -### From RabbitMQ to Apache Kafka - -Assuming you have RabbitMQ and Kafka running, start the application and send a Message to RabbitMQ. - -We included a https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent-stream/src/test/java/io/spring/cloudevent/DemoApplicationTests.java[demo test case] which effectively automates this demo by sending Cloud Event to RabbitMQ and receives one from Apache Kafka. - -``` -Message messageToAMQP = CloudEventMessageBuilder - .withData("{\"firstName\":\"John\", \"lastName\":\"Doe\"}".getBytes()) - .setSource("https://cloudevent.demo") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(CloudEventMessageUtils.AMQP_ATTR_PREFIX); - -rabbitTemplate.send("hire-in-0", "#", messageToAMQP); -Message resultFromKafka = queue.poll(2000, TimeUnit.MILLISECONDS); -System.out.println("Result Message: " + resultFromKafka); -. . . -``` - -Note how we are using CloudEventMessageBuilder here to only set source as Cloud Event attribute while relying on default values for the rest of the -required Cloud Event attributes. We’re also using build(CloudEventMessageUtils.AMQP_ATTR_PREFIX) to ensure that the attributes are prefixed with `cloudEvents:` -prefix (see Cloud Events AMQP protocol bindings). -Also note that on the receiving end Cloud Events attributes are now prefixed with `ce_` prefix (see Cloud Events Kafka protocol bindings), -since it was determined by the framework that the target destination is Apache Kafka. -This last point is worth elaborating a bit. We already established that setting Cloud Event attributes is a non-functional aspect and because -of it we’ve exposed a mechanism for you to deal with it outside of your business logic. But what about attribute prefixes? Note that we are running the -same code in different execution contexts. This means that the attribute prefixes actually depend on the execution context. So by being aware of the execution -context, the framework ensures the correctness of the Cloud Event attribute prefixes. - -You can also use http://localhost:15672/[RabbitMQ dashboard] (if you have it installed) and send message to `hire-in-0` exchange. -To stay compliant with Cloud Event specification you should provide attributes with AMQP appropriate prefixes (i.e., `cloudEvents:`). For example: - -``` -cloudEvents:specversion=1.0 -cloudEvents:type=hire -cloudEvents:source:spring.io/spring-event -cloudEvents:id=0001 -``` - -And your data: -``` -{"firstName":"John", "lastName":"Doe"} -``` diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw b/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw.cmd b/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml deleted file mode 100644 index 7384a7634..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/pom.xml +++ /dev/null @@ -1,169 +0,0 @@ - - - 4.0.0 - io.spring.sample - function-sample-cloudevent-stream - 0.0.1-SNAPSHOT - function-sample-cloudevent-stream - Demo project for Spring Boot - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.cloud - spring-cloud-function-deployer - - - org.springframework.cloud - spring-cloud-stream - 4.1.0-SNAPSHOT - - - - org.springframework.cloud - spring-cloud-stream-binder-rabbit - 4.1.0-SNAPSHOT - - - - - - org.springframework.cloud - spring-cloud-stream-binder-kafka - 4.1.0-SNAPSHOT - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-surefire-plugin - - - **/*Tests.java - **/*Test.java - - - **/Abstract*.java - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - - diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/DemoApplication.java b/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/DemoApplication.java deleted file mode 100644 index 3e59c45ef..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/DemoApplication.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.spring.cloudevent; - -import java.net.URI; -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.cloudevent.CloudEventHeaderEnricher; -import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder; -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -@SpringBootApplication -public class DemoApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(DemoApplication.class, args); - } - - @Bean - public Function hire() { - return person -> { - Employee employee = new Employee(person); - return employee; - }; - } - - // uncomment while keeping the above POJO function -// @Bean -// public CloudEventHeaderEnricher cloudEventEnricher() { -// return messageBuilder -> messageBuilder.setSource("http://spring.io/cloudevent") -// .setType("sample").setId("987654"); -// } - - // uncomment while commenting the previous two beans -// @Bean -// public Function, Message> hire() { -// return message -> { -// Person person = message.getPayload(); -// Employee employee = new Employee(person); -// return CloudEventMessageBuilder.withData(employee).setId("123456") -// .setSource(URI.create("https://spring.cloudevenets.sample")).build(); -// }; -// } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Employee.java b/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Employee.java deleted file mode 100644 index e1f04615e..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Employee.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.spring.cloudevent; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Random; - -public class Employee { - - private Person person; - - private int id; - - public Employee() { - - } - - public Employee(Person person) { - this.person = person; - this.id = new Random().nextInt(1000); - } - - public Person getPerson() { - return person; - } - - public void setPerson(Person person) { - this.person = person; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getMessage() { - return "Employee " + id + " was hired on " + new SimpleDateFormat("dd-MM-yyyy").format(new Date()); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Person.java b/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Person.java deleted file mode 100644 index 99ded7514..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/java/io/spring/cloudevent/Person.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.spring.cloudevent; - -public class Person { - - private String firstName; - - private String lastName; - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/resources/application.yaml b/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/resources/application.yaml deleted file mode 100644 index 7dbd85990..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/main/resources/application.yaml +++ /dev/null @@ -1,15 +0,0 @@ -spring: - cloud: - stream: - bindings: - hire-in-0: - binder: rabbit1 - hire-out-0: - binder: kafka1 - binders: - rabbit1: - type: rabbit - kafka1: - type: kafka - function: - definition: hire \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/test/java/io/spring/cloudevent/DemoApplicationTests.java b/spring-cloud-function-samples/function-sample-cloudevent-stream/src/test/java/io/spring/cloudevent/DemoApplicationTests.java deleted file mode 100644 index eb57b7bc6..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent-stream/src/test/java/io/spring/cloudevent/DemoApplicationTests.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.spring.cloudevent; - -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Collections; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.apache.kafka.clients.admin.KafkaAdminClient; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ConditionEvaluationResult; -import org.junit.jupiter.api.extension.ExecutionCondition; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; -import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder; -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.util.MimeTypeUtils; - -@SpringBootTest -@ExtendWith(DemoApplicationTests.TestRule.class) -public class DemoApplicationTests { - - @Autowired - private RabbitMessagingTemplate rabbitTemplate; - - ArrayBlockingQueue> queue = new ArrayBlockingQueue<>(1); - - @Test - public void test() throws Exception { - Message messageToAMQP = CloudEventMessageBuilder - .withData("{\"firstName\":\"John\", \"lastName\":\"Doe\"}".getBytes()) - .setSource("https://cloudevent.demo") - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(CloudEventMessageUtils.AMQP_ATTR_PREFIX); - - rabbitTemplate.send("hire-in-0", "#", messageToAMQP); - - Message resultFromKafka = queue.poll(2000, TimeUnit.MILLISECONDS); - System.out.println("Result Message: " + resultFromKafka); - System.out.println("Cloud Event 'specversion': " + CloudEventMessageUtils.getSpecVersion(resultFromKafka)); - System.out.println("Cloud Event 'source': " + CloudEventMessageUtils.getSource(resultFromKafka)); - System.out.println("Cloud Event 'id': " + CloudEventMessageUtils.getId(resultFromKafka)); - System.out.println("Cloud Event 'type': " + CloudEventMessageUtils.getType(resultFromKafka)); - - } - - @KafkaListener(id = "test", topics = "hire-out-0", clientIdPrefix = "cloudEvents") - public void listen(Message message) { - queue.add(message); - } - - public static class TestRule implements ExecutionCondition { - @Override - public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - try { - new CachingConnectionFactory("localhost").createConnection(); - try { - Socket socket = new Socket(); - socket.connect(new InetSocketAddress("localhost", 9092)); - socket.close(); - } - catch (Exception e) { - System.out.println("Kafka is not available on localhost:9092"); - return ConditionEvaluationResult.disabled("Kafka is not available on localhost, default port"); - } - } - catch (Exception e) { - System.out.println("RabbitMQ is not available on localhost:5672"); - return ConditionEvaluationResult.disabled("Rabbit is not available on localhost:5672"); - } - - - return ConditionEvaluationResult.enabled("All is good"); - } - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent/.gitignore b/spring-cloud-function-samples/function-sample-cloudevent/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572ce..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-cloudevent/README.adoc b/spring-cloud-function-samples/function-sample-cloudevent/README.adoc deleted file mode 100644 index 774439185..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/README.adoc +++ /dev/null @@ -1,47 +0,0 @@ -## Examples of Cloud Events with Spring via HTTP - -### Introduction -The current example uses spring-cloud-function framework as its core which allows users to only worry about functional aspects of -their requirement while taking care-off non-functional aspects. For more information on Spring Cloud Function please visit -our https://spring.io/projects/spring-cloud-function[project page]. - -The example consists of a Spring boot configuration class -https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java[DemoApplication] -which contains a sample function which you can interact with following via HTTP. - -Given that SCF allows function to be exposed as REST endpoints, you can post cloud event to any of the -functions by using function name as path (e.g., `localhost:8080/`). - - -Here is an example of curl command posting a cloud event in binary-mode: - -[source, text] ----- -curl -w'\n' localhost:8080/hire \ - -H "ce-id: 0001" \ - -H "ce-specversion: 1.0" \ - -H "ce-type: hire" \ - -H "ce-source: spring.io/spring-event" \ - -H "Content-Type: application/json" \ - -d '{"firstName":"John", "lastName":"Doe"}' -i ----- - -And here is an example of curl command posting a cloud event in structured-mode: - -[source, text] ----- -curl -w'\n' localhost:8080/asString \ - -H "Content-Type: application/cloudevents+json" \ - -d '{ - "specversion" : "1.0", - "type" : "org.springframework", - "source" : "https://spring.io/", - "id" : "A234-1234-1234", - "datacontenttype" : "application/json", - "data" : { - "firstName" : "John", - "lastName" : "Doe" - } -}' ----- - diff --git a/spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-binary.png b/spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-binary.png deleted file mode 100644 index 52bd151178d44624ab969db2330da59ab2849aed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185236 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

MM^R#92HHYWz5b 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%0Djn!!&GFb?Tdw&ap}UKzq{sIW`3xVAl2%+tMQ; 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

yUc!>yK9*S0 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 z

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

BxdcyxgJog>=_x90>u-y{qd)^zyADf{pB#g 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 TG`hF|{Fxs(vY)Wm<--2};dK|H diff --git a/spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-structured.png b/spring-cloud-function-samples/function-sample-cloudevent/images/rabbit-send-structured.png deleted file mode 100644 index d5b45d3e7bca41cc366ad7541f0111ea76462549..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184685 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 z 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

See the PubSubMessage definition for reference: - * https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage - * - * @author Mike Eltsufin - */ -public class PubSubMessage { - - private String data; - - private Map attributes; - - private String messageId; - - private String publishTime; - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public String getMessageId() { - return messageId; - } - - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - public String getPublishTime() { - return publishTime; - } - - public void setPublishTime(String publishTime) { - this.publishTime = publishTime; - } - -} diff --git a/spring-cloud-function-samples/function-sample-gcp-background/src/main/resources/META-INF/MANIFEST.MF b/spring-cloud-function-samples/function-sample-gcp-background/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index edd9a3bf2..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-background/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Main-Class: com.example.BackgroundFunctionMain diff --git a/spring-cloud-function-samples/function-sample-gcp-http/README.adoc b/spring-cloud-function-samples/function-sample-gcp-http/README.adoc deleted file mode 100644 index 43a1c422c..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/README.adoc +++ /dev/null @@ -1,46 +0,0 @@ -:branch: master - -=== Google Cloud Functions Sample Application - -===== Test locally - -Run the function: - ----- -mvn function:run ----- - -Invoke the HTTP function: - ----- -curl http://localhost:8080/ -d "hello" ----- - -===== Deploy to GCP - -Package the application. - ----- -mvn package ----- - -You should see the fat jar in the `target/deploy` directory. - -Make sure that you have the https://cloud.google.com/sdk/install[Cloud SDK CLI] installed. - -Run the following command from the project root to deploy. - ----- -gcloud functions deploy function-sample-gcp-http \ ---entry-point org.springframework.cloud.function.adapter.gcp.GcfJarLauncher \ ---runtime java17 \ ---trigger-http \ ---source target/deploy \ ---memory 512MB ----- - -Invoke the HTTP function: - ----- -curl https://REGION-PROJECT_ID.cloudfunctions.net/function-sample-gcp-http -d "hello" ----- diff --git a/spring-cloud-function-samples/function-sample-gcp-http/pom.xml b/spring-cloud-function-samples/function-sample-gcp-http/pom.xml deleted file mode 100644 index b5da383c9..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/pom.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - - 4.0.0 - - io.spring.sample - function-sample-gcp-http - 0.0.1-SNAPSHOT - jar - - function-sample-gcp-http - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - 4.1.0-SNAPSHOT - - - - - org.springframework - spring-web - test - - - org.springframework.boot - spring-boot-test - test - - - org.junit.jupiter - junit-jupiter - test - - - org.assertj - assertj-core - test - - - com.google.cloud.functions.invoker - java-function-invoker - 1.0.0-alpha-2-rc5 - test - - - - - - - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - target/deploy - - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - ${spring-cloud-function.version} - - - - - - com.google.cloud.functions - function-maven-plugin - 0.9.1 - - org.springframework.cloud.function.adapter.gcp.GcfJarLauncher - 8080 - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-gcp-http/src/main/java/com/example/CloudFunctionMain.java b/spring-cloud-function-samples/function-sample-gcp-http/src/main/java/com/example/CloudFunctionMain.java deleted file mode 100644 index dc5f213ab..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/src/main/java/com/example/CloudFunctionMain.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020-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 com.example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class CloudFunctionMain { - - public static void main(String[] args) { - SpringApplication.run(CloudFunctionMain.class, args); - } - - @Bean - public Function function() { - return value -> value.toUpperCase(); - } -} diff --git a/spring-cloud-function-samples/function-sample-gcp-http/src/main/resources/META-INF/MANIFEST.MF b/spring-cloud-function-samples/function-sample-gcp-http/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 6bd1d52fe..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Main-Class: com.example.CloudFunctionMain diff --git a/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/FunctionSampleGcpIntegrationTest.java b/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/FunctionSampleGcpIntegrationTest.java deleted file mode 100644 index 2ebd4f819..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/FunctionSampleGcpIntegrationTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020-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 com.example; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.web.client.TestRestTemplate; - -import static org.assertj.core.api.Assertions.assertThat; - -public class FunctionSampleGcpIntegrationTest { - - private TestRestTemplate rest = new TestRestTemplate(); - - @Test - public void testSample() throws IOException, InterruptedException { - try (LocalServerTestSupport.ServerProcess process = LocalServerTestSupport.startServer(CloudFunctionMain.class)) { - String result = rest.postForObject("http://localhost:8080/", "Hello", String.class); - assertThat(result).isEqualTo("\"HELLO\""); - } - } -} diff --git a/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/LocalServerTestSupport.java b/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/LocalServerTestSupport.java deleted file mode 100644 index 8bbe71943..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/LocalServerTestSupport.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2020-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 com.example; - -import java.io.*; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import com.google.cloud.functions.invoker.runner.Invoker; - -import org.springframework.cloud.function.adapter.gcp.GcfJarLauncher; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test support class for running tests on the local Cloud Function server. - * - * @author Daniel Zou - * @author Mike Eltsufin - */ -final public class LocalServerTestSupport { - - private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(); - - private static final String SERVER_READY_STRING = "Started ServerConnector"; - - private static AtomicInteger nextPort = new AtomicInteger(8080); - - private LocalServerTestSupport() { - } - - public static ServerProcess startServer(Class springApplicationMainClass) - throws InterruptedException, IOException { - - // Get the Java class path. - String myClassPath = System.getProperty("java.class.path"); - assertThat(myClassPath).isNotNull(); - - // Setup the Java Process command line string - List command = Arrays.asList(getJavaCommand(), "-classpath", myClassPath, Invoker.class.getName()); - ProcessBuilder processBuilder = new ProcessBuilder().command(command).redirectErrorStream(true); - - // Set environment variables. - Map environment = new HashMap<>(); - environment.put("PORT", String.valueOf(nextPort.getAndIncrement())); - environment.put("K_SERVICE", "test-function"); - environment.put("FUNCTION_SIGNATURE_TYPE", "http"); - environment.put("FUNCTION_TARGET", GcfJarLauncher.class.getCanonicalName()); - environment.put("MAIN_CLASS", springApplicationMainClass.getCanonicalName()); - processBuilder.environment().putAll(environment); - - // Start the process and monitor the output logs in a separate thread. - // Once the SERVER_READY_STRING is found in the logs, we know we are ready. - Process serverProcess = processBuilder.start(); - CountDownLatch ready = new CountDownLatch(1); - - EXECUTOR.submit(() -> monitorOutput(serverProcess.getInputStream(), ready)); - boolean serverReady = ready.await(5, TimeUnit.SECONDS); - if (!serverReady) { - serverProcess.destroy(); - throw new AssertionError("Server never became ready"); - } - - return new ServerProcess(serverProcess); - } - - private static void monitorOutput(InputStream processOutput, CountDownLatch ready) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(processOutput))) { - String line; - while ((line = reader.readLine()) != null) { - if (line.contains(SERVER_READY_STRING)) { - ready.countDown(); - } - - System.out.println(line); - - if (line.contains("WARNING")) { - throw new AssertionError("Found warning in server output:\n" + line); - } - } - } - catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - /** - * Returns the path to the java executable. - */ - private static String getJavaCommand() { - File javaHome = new File(System.getProperty("java.home")); - assertThat(javaHome.exists()).isTrue(); - - File javaBin = new File(javaHome, "bin"); - File javaCommand = new File(javaBin, "java"); - assertThat(javaCommand.exists()).isTrue(); - - return javaCommand.toString(); - } - - static class ServerProcess implements AutoCloseable { - - private final Process process; - - ServerProcess(Process process) { - this.process = process; - } - - Process process() { - return process; - } - - @Override - public void close() { - process().destroy(); - } - } -} diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.gitignore b/spring-cloud-function-samples/function-sample-grpc-cloudevent/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index abd303b67..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw b/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw.cmd b/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml b/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml deleted file mode 100644 index 720ee2e24..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/pom.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - 4.0.0 - - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - com.example.grpc - function-sample-grpc-cloudevent - 0.0.1-SNAPSHOT - function-sample-grpc-cloudevent - Demo project for Spring Boot - - 4.1.0-SNAPSHOT - 1.55.1 - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-function-grpc-cloudevent-ext - - - - io.grpc - grpc-netty - ${grpc.version} - - - io.grpc - grpc-protobuf - ${grpc.version} - - - io.grpc - grpc-stub - ${grpc.version} - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - kr.motd.maven - os-maven-plugin - 1.6.1 - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.6.1 - - - com.google.protobuf:protoc:3.23.0:exe:${os.detected.classifier} - - grpc-java - - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - - compile - compile-custom - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/java/com/example/grpc/demo/DemoGrpcApplication.java b/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/java/com/example/grpc/demo/DemoGrpcApplication.java deleted file mode 100644 index 83d7bcc33..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/java/com/example/grpc/demo/DemoGrpcApplication.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.example.grpc.demo; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.grpc.MessagingServiceGrpc; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import com.google.protobuf.DescriptorProtos.FileDescriptorProto; -import com.google.protobuf.DescriptorProtos.FileDescriptorSet; -import com.google.protobuf.Descriptors.FileDescriptor; -import com.google.protobuf.ProtocolStringList; - -import io.cloudevents.v1.CloudEventServiceGrpc; -import io.cloudevents.v1.proto.CloudEvent; -import io.cloudevents.v1.proto.CloudEvent.CloudEventAttributeValue; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; - -@SpringBootApplication -public class DemoGrpcApplication { - - public static void main(String[] args) throws Exception { - - SpringApplication.run(DemoGrpcApplication.class, - "--spring.cloud.function.grpc.service-class-name=org.springframework.cloud.function.grpc.ce.CloudEventHandler"); - - CloudEvent cloudEvent = CloudEvent.newBuilder() - .setTextData("{\"event_name\":\"SCF supports CloudEvent gRPC\"}") - .setSource("http://springsource.com") - .setId("12345") - .setSpecVersion("1.0") - .setType("org.springframework") - .putAttributes("name", CloudEventAttributeValue.newBuilder().setCeString("oleg").build()) - .putAttributes("fluent_in_french", CloudEventAttributeValue.newBuilder().setCeBoolean(false).build()) - .build(); - - ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 6048) - .usePlaintext().build(); - - CloudEventServiceGrpc.CloudEventServiceBlockingStub stub = CloudEventServiceGrpc.newBlockingStub(channel); - CloudEvent reply = stub.requestReply(cloudEvent); - System.out.println(reply); - - } - - @Bean - public Function, Message> uppercase() { - return message -> { - return MessageBuilder.withPayload(message.getPayload().toUpperCase()) - .copyHeaders(message.getHeaders()) - .setHeader("uppercased", "true") - .build(); - }; - } -} - - diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEvent.proto b/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEvent.proto deleted file mode 100644 index 7952c1f79..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEvent.proto +++ /dev/null @@ -1,49 +0,0 @@ -syntax = "proto3"; - -package io.cloudevents.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "cloudevents.io/genproto/v1"; -option java_package = "io.cloudevents.v1.proto"; -option java_multiple_files = true; - -message CloudEvent { - - // -- CloudEvent Context Attributes - - // Required Attributes - string id = 1; - string source = 2; // URI-reference - string spec_version = 3; - string type = 4; - - // Optional & Extension Attributes - map attributes = 5; - - // -- CloudEvent Data (Bytes, Text, or Proto) - oneof data { - bytes binary_data = 6; - string text_data = 7; - google.protobuf.Any proto_data = 8; - } - - /** - * The CloudEvent specification defines - * seven attribute value types... - */ - - message CloudEventAttributeValue { - - oneof attr { - bool ce_boolean = 1; - int32 ce_integer = 2; - string ce_string = 3; - bytes ce_bytes = 4; - string ce_uri = 5; - string ce_uri_ref = 6; - google.protobuf.Timestamp ce_timestamp = 7; - } - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEventService.proto b/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEventService.proto deleted file mode 100644 index 1a7be6a74..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/proto/CloudEventService.proto +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "proto3"; - -package io.cloudevents.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; -import "CloudEvent.proto"; - -service CloudEventService { - rpc biStream(stream io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc clientStream(stream io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); - - rpc serverStream(io.cloudevents.v1.CloudEvent) returns (stream io.cloudevents.v1.CloudEvent); - - rpc requestReply(io.cloudevents.v1.CloudEvent) returns (io.cloudevents.v1.CloudEvent); -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/test/java/com/example/grpc/demo/DemoGrpcApplicationTests.java b/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/test/java/com/example/grpc/demo/DemoGrpcApplicationTests.java deleted file mode 100644 index 452a7eed5..000000000 --- a/spring-cloud-function-samples/function-sample-grpc-cloudevent/src/test/java/com/example/grpc/demo/DemoGrpcApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.grpc.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DemoGrpcApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/.gitignore b/spring-cloud-function-samples/function-sample-kotlin-web/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f324..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572ce..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/README.adoc b/spring-cloud-function-samples/function-sample-kotlin-web/README.adoc deleted file mode 100644 index bceb0ad5e..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/README.adoc +++ /dev/null @@ -1,45 +0,0 @@ -## Examples of Kotlin support in Spring Cloud Function - -### Introduction -This example provides a configuration with a single Kotlin function - -[source, kotlin] ----- -@Configuration -class DemoKotlinConfiguration { - @Bean - fun uppercase(): (String) -> String { - return { it.toUpperCase() } - } -} ----- - -It also adds web support - -[source, xml] ----- - - org.springframework.cloud - spring-cloud-function-kotlin - ${spring-cloud-function.version} - - - org.springframework.cloud - spring-cloud-function-web - ${spring-cloud-function.version} - ----- - -Once you start the application, simply issue GET request either thru browser or curl: - -[source, text] ----- -curl http://localhost:8080/uppercase/hello ----- - -you should see the output - -[source, text] ----- -HELLO ----- diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-binary.png b/spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-binary.png deleted file mode 100644 index 52bd151178d44624ab969db2330da59ab2849aed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185236 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

MM^R#92HHYWz5b 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%0Djn!!&GFb?Tdw&ap}UKzq{sIW`3xVAl2%+tMQ; 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

yUc!>yK9*S0 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 z

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

BxdcyxgJog>=_x90>u-y{qd)^zyADf{pB#g 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 TG`hF|{Fxs(vY)Wm<--2};dK|H diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-structured.png b/spring-cloud-function-samples/function-sample-kotlin-web/images/rabbit-send-structured.png deleted file mode 100644 index d5b45d3e7bca41cc366ad7541f0111ea76462549..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184685 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 z 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save ( ) { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/spring-cloud-function-samples/function-sample-spring-integration/gradlew.bat b/spring-cloud-function-samples/function-sample-spring-integration/gradlew.bat deleted file mode 100644 index f9553162f..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-spring-integration/pom.xml b/spring-cloud-function-samples/function-sample-spring-integration/pom.xml deleted file mode 100644 index 40dd8b3d0..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/pom.xml +++ /dev/null @@ -1,140 +0,0 @@ - - 4.0.0 - - io.spring.sample - function-sample-spring-integration - 0.0.1-SNAPSHOT - jar - function-sample-spring-integration - Spring Cloud Function Web Support - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 17 - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-starter-function-webflux - - - org.springframework.boot - spring-boot-starter-integration - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.springframework.boot.experimental - spring-boot-thin-layout - 1.0.27.RELEASE - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-spring-integration/settings.gradle b/spring-cloud-function-samples/function-sample-spring-integration/settings.gradle deleted file mode 100644 index 55d13ed71..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'function-sample-spring-integration' diff --git a/spring-cloud-function-samples/function-sample-spring-integration/src/main/java/example/FunctionSampleSpringIntegrationApplication.java b/spring-cloud-function-samples/function-sample-spring-integration/src/main/java/example/FunctionSampleSpringIntegrationApplication.java deleted file mode 100644 index f6103c277..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/src/main/java/example/FunctionSampleSpringIntegrationApplication.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2023 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 java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.handler.LoggingHandler; -import org.springframework.messaging.Message; - -@SpringBootApplication -public class FunctionSampleSpringIntegrationApplication { - - public static void main(String[] args) { - SpringApplication.run(FunctionSampleSpringIntegrationApplication.class, args); - } - - @Bean - public IntegrationFlow uppercaseFlow() { - return IntegrationFlow.from(MessageFunction.class, (gateway) -> gateway.beanName("uppercase")) - .transform(String::toUpperCase) - .log(LoggingHandler.Level.WARN) - .get(); - } - - public interface MessageFunction extends Function, Message> { - - } - -} diff --git a/spring-cloud-function-samples/function-sample-spring-integration/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-spring-integration/src/main/resources/application.properties deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-function-samples/function-sample-spring-integration/src/test/java/example/FunctionSampleSpringIntegrationApplicationTests.java b/spring-cloud-function-samples/function-sample-spring-integration/src/test/java/example/FunctionSampleSpringIntegrationApplicationTests.java deleted file mode 100644 index b6ee09a11..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/src/test/java/example/FunctionSampleSpringIntegrationApplicationTests.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019-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 static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class FunctionSampleSpringIntegrationApplicationTests { - - @Autowired - private TestRestTemplate restTemplate; - - @Test - public void upperCase() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - HttpEntity requestEntity = new HttpEntity<>("[\"foo\", \"bar\"]", httpHeaders); - HttpEntity result = this.restTemplate.postForEntity("/uppercase", requestEntity, String.class); - assertThat(result.getBody()).isEqualTo("[\"FOO\",\"BAR\"]"); - } - -} diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/README.md b/spring-cloud-function-samples/function-sample-supplier-exporter/README.md deleted file mode 100644 index 560073481..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/README.md +++ /dev/null @@ -1,16 +0,0 @@ -AWS Lambda custom runtime. - -``` -$ ./build.sh -$ ./mvnw package -P native -``` - -builds a native-zip ZIP file in target. Upload it to AWS and set the handler to "foobar". - -To test locally, run the `TestServer` and then the `DemoApplication` (either in a JVM or natively). Then POST some data into the test server: - -``` -$ curl localhost:8000/add -d world -H "Content-Type: text/plain" -``` - -There is a unit test that does the same thing. Also the `build.sh` script orchestrates the same test for the native image. diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh b/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh deleted file mode 100644 index ec45e4d25..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/compile.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash - -ARTIFACT=function-aws -MAINCLASS=com.example.demo.DemoApplication -VERSION=0.0.1-SNAPSHOT -FEATURE=../../../../spring-graal-native/target/spring-graal-native-0.7.0.BUILD-SNAPSHOT.jar - -GREEN='\033[0;32m' -RED='\033[0;31m' -NC='\033[0m' - -rm -rf target -mkdir -p target/native-image - -echo "Packaging $ARTIFACT with Maven" -mvn -DskipTests package > target/native-image/output.txt - -JAR="$ARTIFACT-$VERSION.jar" -rm -f $ARTIFACT -echo "Unpacking $JAR" -cd target/native-image -jar -xvf ../$JAR >/dev/null 2>&1 -cp -R META-INF BOOT-INF/classes - -LIBPATH=`find BOOT-INF/lib | tr '\n' ':'` -CP=BOOT-INF/classes:$LIBPATH:$FEATURE - -if [ ! -f "$FEATURE" ]; then - printf "${RED}FAILURE${NC}: $FEATURE does not exist, please build the root project before building this sample.\n" - exit 1 -fi - -GRAALVM_VERSION=`native-image --version` -echo "Compiling $ARTIFACT with $GRAALVM_VERSION" -{ time native-image \ - --verbose \ - --no-server \ - --no-fallback \ - --initialize-at-build-time \ - -H:+PrintMethodHistogram \ - -H:+TraceClassInitialization \ - -H:Name=$ARTIFACT \ - -H:+ReportExceptionStackTraces \ - -Dspring.graal.remove-unused-autoconfig=true \ - -Dspring.graal.remove-yaml-support=true \ - -cp $CP $MAINCLASS >> output.txt ; } 2>> output.txt - -if [[ -f $ARTIFACT ]] -then - printf "${GREEN}SUCCESS${NC}\n" - mv ./$ARTIFACT .. - exit 0 -else - cat output.txt - printf "${RED}FAILURE${NC}: an error occurred when compiling the native-image.\n" - exit 1 -fi - diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml b/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml deleted file mode 100644 index be230cf80..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/pom.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-aws-supplier-exporter - 0.0.1-SNAPSHOT - jar - function-sample-aws-supplier-exporter - Spring Cloud Function Example showing Supplier Exporter - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-webflux - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - org.springframework.boot - spring-boot-starter-test - test - - - org.awaitility - awaitility - test - - - org.testcontainers - testcontainers - 1.14.3 - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - maven-surefire-plugin - - - com/example/demo/ContainerTests.java - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - - integration - - - - maven-surefire-plugin - 2.22.0 - - - integration-test - - test - - - - none - - - com/example/demo/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-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 deleted file mode 100644 index fd7b20ea4..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/java/com/example/demo/DemoApplication.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.example.demo; - -import java.util.function.Function; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.cloud.function.context.FunctionRegistration; -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; - -@SpringBootConfiguration(proxyBeanMethods = false) -public class DemoApplication - implements ApplicationContextInitializer { - - public static void main(String[] args) { - FunctionalSpringApplication.run(DemoApplication.class, args); - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("foobar", FunctionRegistration.class, - () -> new FunctionRegistration<>(new Foobar()) - .type(FunctionTypeUtils.functionType(Foo.class, Foo.class))); - } - -} - -class Foo { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Foo(String name) { - this.name = name; - } - - Foo() { - } -} - -class Foobar implements Function { - - @Override - public Foo apply(Foo input) { - System.err.println("HI: " + input.getName()); - return new Foo("hi " + input.getName() + "!"); - } -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json deleted file mode 100644 index c5f6007b7..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/META-INF/native-image/reflect-config.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "name": "com.example.demo.Foo", - "allDeclaredConstructors": true, - "allDeclaredMethods": true - } -] \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties deleted file mode 100644 index 9e8695a2c..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.cloud.function.web.export.enabled=true -spring.cloud.function.web.export.debug=true -spring.main.web-application-type=none -logging.level.org.springframework.cloud=DEBUG \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/ContainerTests.java b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/ContainerTests.java deleted file mode 100644 index 0b16a54a5..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/java/com/example/demo/ContainerTests.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2020-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 com.example.demo; - -import java.util.concurrent.TimeUnit; - -import org.awaitility.Awaitility; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.output.ToStringConsumer; -import org.testcontainers.utility.MountableFile; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class ContainerTests { - - @Test - void test() throws Exception { - ToStringConsumer consumer = new ToStringConsumer(); - try (@SuppressWarnings("resource") - GenericContainer container = new GenericContainer<>("lambci/lambda:provided").withLogConsumer(consumer) - .withCopyFileToContainer(MountableFile.forClasspathResource("bootstrap"), "/var/task/") - .withEnv("DOCKER_LAMBDA_STAY_OPEN", "1").withExposedPorts(9001)) { - container.start(); - int port = container.getFirstMappedPort(); - String host = container.getHost(); - System.err.println(host + ":" + port); - DemoApplication.main(new String[] { "--AWS_LAMBDA_RUNTIME_API=" + host + ":" + port, "--_HANDLER=foobar", - "--logging.level.org.springframework=DEBUG" }); - ResponseEntity response = Awaitility.waitAtMost(30, TimeUnit.SECONDS).until(() -> { - ResponseEntity result = new RestTemplate().postForEntity( - "http://" + host + ":" + port + "/2015-03-31/functions/foobar/invocations", - "{\"name\":\"foo\"}", String.class); - return result; - }, result -> result != null); - assertThat(response.getBody()).contains("hi foo!"); - assertThat(response.getHeaders()).containsKey("X-Amzn-Requestid"); - } - String output = consumer.toUtf8String(); - assertThat(output).contains("Lambda API listening on port 9001"); - assertThat(output).contains("START RequestId:"); - assertThat(output).contains("END RequestId:"); - } - -} diff --git a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/resources/bootstrap b/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/resources/bootstrap deleted file mode 100755 index 142d4caad..000000000 --- a/spring-cloud-function-samples/function-sample-supplier-exporter/src/test/resources/bootstrap +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -while true -do - sleep 1 -done \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample/.jdk8 b/spring-cloud-function-samples/function-sample/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample/build.gradle b/spring-cloud-function-samples/function-sample/build.gradle deleted file mode 100644 index f2976cab9..000000000 --- a/spring-cloud-function-samples/function-sample/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.1.0.BUILD-SNAPSHOT' - wrapperVersion = '1.0.13.RELEASE' - } - repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/plugins-snapshot" } - maven { url "https://repo.spring.io/plugins-milestone" } - } - dependencies { - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'spring-boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' - -group = 'com.example' -version = '0.0.1-SNAPSHOT' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "2.0.0.BUILD-SNAPSHOT" -} - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile('org.springframework.cloud:spring-cloud-starter-function-web') - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample/gradlew.bat b/spring-cloud-function-samples/function-sample/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample/pom.xml b/spring-cloud-function-samples/function-sample/pom.xml deleted file mode 100644 index 5a81da08b..000000000 --- a/spring-cloud-function-samples/function-sample/pom.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample - 0.0.1-SNAPSHOT - jar - function-sample - Spring Cloud Function Web Support - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.cloud - spring-cloud-starter-function-webflux - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample/src/main/java/com/example/Client.java b/spring-cloud-function-samples/function-sample/src/main/java/com/example/Client.java deleted file mode 100644 index 516fa3a1c..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/java/com/example/Client.java +++ /dev/null @@ -1,44 +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 com.example; - -import org.springframework.web.reactive.function.client.WebClient; - -/** - * Sample client to test infinite stream from function. - * - * @author Oleg Zhurakousky - * - */ -public class Client { - - public static void main(String[] args) throws Exception { - WebClient client = WebClient.create(); - WebClient.ResponseSpec responseSpec = client.post() - .uri("http://localhost:8080/infinite") - .header("accept", "text/event-stream") - .retrieve(); - - responseSpec.bodyToFlux(String.class).subscribe(v -> { - System.out.println(v); - }); - - System.in.read(); - - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/main/java/com/example/SampleApplication.java b/spring-cloud-function-samples/function-sample/src/main/java/com/example/SampleApplication.java deleted file mode 100644 index f26aec07f..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/java/com/example/SampleApplication.java +++ /dev/null @@ -1,67 +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 com.example; - -import java.time.Duration; -import java.util.function.Function; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; - -// @checkstyle:off -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(SampleApplication.class, "--management.endpoints.web.exposure.include=functions"); - } - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - @Bean - public Function, Integer> uppercaseMessage() { - return value -> value.getPayload().toUpperCase().length(); - } - - @Bean - public Function, Flux> lowercase() { - return flux -> flux.map(value -> value.toLowerCase()); - } - - @Bean - public Supplier hello() { - return () -> "hello"; - } - - @Bean - public Supplier> infinite() { - return () -> Flux - .interval(Duration.ofSeconds(1)) - .log() - .map(counter -> String.format("Counter: %s", counter)); - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/CharCounter.java b/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/CharCounter.java deleted file mode 100644 index 5c54b7371..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/CharCounter.java +++ /dev/null @@ -1,31 +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 com.example.functions; - -import java.util.function.Function; - -/** - * @author Mark Fisher - */ -public class CharCounter implements Function { - - @Override - public Integer apply(String word) { - return word.length(); - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Exclaimer.java b/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Exclaimer.java deleted file mode 100644 index 434a34e2d..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Exclaimer.java +++ /dev/null @@ -1,33 +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 com.example.functions; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; - -/** - * @author Mark Fisher - */ -public class Exclaimer implements Function, Flux> { - - @Override - public Flux apply(Flux words) { - return words.map(word -> word + "!!!"); - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Greeter.java b/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Greeter.java deleted file mode 100644 index fdf66f032..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/Greeter.java +++ /dev/null @@ -1,31 +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 com.example.functions; - -import java.util.function.Function; - -/** - * @author Mark Fisher - */ -public class Greeter implements Function { - - @Override - public String apply(String name) { - return "Hello " + name; - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/main/resources/META-INF/thin-rabbit.properties b/spring-cloud-function-samples/function-sample/src/main/resources/META-INF/thin-rabbit.properties deleted file mode 100644 index 6906ff808..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/resources/META-INF/thin-rabbit.properties +++ /dev/null @@ -1,5 +0,0 @@ -boms.spring-cloud-dependencies:org.springframework.cloud:spring-cloud-dependencies:Edgware.SR3 -dependencies.spring-cloud-function-stream:org.springframework.cloud:spring-cloud-function-stream -dependencies.spring-cloud-stream-rabbit:org.springframework.cloud:spring-cloud-starter-stream-rabbit -exclusions.spring-cloud-function-web:org.springframework.cloud:spring-cloud-starter-function-web -exclusions.http-client:com.rabbitmq:http-client diff --git a/spring-cloud-function-samples/function-sample/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample/src/main/resources/application.properties deleted file mode 100644 index c1a56fa72..000000000 --- a/spring-cloud-function-samples/function-sample/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.cloud.function.stream.processor.name:uppercase -spring.cloud.function.scan.packages:com.example.functions diff --git a/spring-cloud-function-samples/function-sample/src/test/java/com/example/FunctionTests.java b/spring-cloud-function-samples/function-sample/src/test/java/com/example/FunctionTests.java deleted file mode 100644 index cae8e9187..000000000 --- a/spring-cloud-function-samples/function-sample/src/test/java/com/example/FunctionTests.java +++ /dev/null @@ -1,75 +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 com.example; - -import java.util.List; - -import com.example.functions.CharCounter; -import com.example.functions.Exclaimer; -import com.example.functions.Greeter; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import static org.assertj.core.api.Assertions.assertThat; - -public class FunctionTests { - - private final SampleApplication functions = new SampleApplication(); - - @Test - public void testUppercase() { - String output = this.functions.uppercase().apply("foobar"); - assertThat(output).isEqualTo("FOOBAR"); - } - - @Test - public void testLowercase() { - Flux output = this.functions.lowercase().apply(Flux.just("FOO", "BAR")); - List results = output.collectList().block(); - assertThat(results.size()).isEqualTo(2); - assertThat(results.get(0)).isEqualTo("foo"); - assertThat(results.get(1)).isEqualTo("bar"); - } - - @Test - public void testHello() { - String output = this.functions.hello().get(); - assertThat(output).isEqualTo("hello"); - } - - @Test - public void testGreeter() { - assertThat(new Greeter().apply("World")).isEqualTo("Hello World"); - } - - @Test - public void testExclaimer() { - Flux input = Flux.just("foo", "bar"); - Flux output = new Exclaimer().apply(input); - List results = output.collectList().block(); - assertThat(results.size()).isEqualTo(2); - assertThat(results.get(0)).isEqualTo("foo!!!"); - assertThat(results.get(1)).isEqualTo("bar!!!"); - } - - @Test - public void testCharCounter() { - assertThat(new CharCounter().apply("this is 21 chars long")) - .isEqualTo((Integer) 21); - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/test/java/com/example/SampleApplicationMvcTests.java b/spring-cloud-function-samples/function-sample/src/test/java/com/example/SampleApplicationMvcTests.java deleted file mode 100644 index b9eb7a8cb..000000000 --- a/spring-cloud-function-samples/function-sample/src/test/java/com/example/SampleApplicationMvcTests.java +++ /dev/null @@ -1,68 +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 com.example; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; - -/** - * @author Dave Syer - */ -@SpringBootTest -@AutoConfigureMockMvc -@Disabled -public class SampleApplicationMvcTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void words() throws Exception { - MvcResult result = this.mockMvc.perform(get("/words")).andReturn(); - mockMvc.perform(asyncDispatch(result)).andExpect(content().string("[\"foo\",\"bar\"]")); - } - - @Test - public void uppercase() throws Exception { - MvcResult result = this.mockMvc.perform(post("/uppercase").contentType(MediaType.TEXT_PLAIN).content("foo")).andReturn(); - mockMvc.perform(asyncDispatch(result)).andExpect(content().string("FOO")); - } - - @Test - public void lowercase() throws Exception { - MvcResult result = this.mockMvc.perform(post("/lowercase").contentType(MediaType.TEXT_PLAIN).content("FOO")).andReturn(); - mockMvc.perform(asyncDispatch(result)).andExpect(content().string("[\"foo\"]")); - } - - @Test - public void lowercaseMulti() throws Exception { - MvcResult result = this.mockMvc.perform(post("/lowercase").contentType(MediaType.APPLICATION_JSON).content("[\"FOO\"]")).andReturn(); - mockMvc.perform(asyncDispatch(result)).andExpect(content().string("[\"foo\"]")); - } - -} diff --git a/spring-cloud-function-samples/function-sample/src/test/java/com/example/WebTestClientTests.java b/spring-cloud-function-samples/function-sample/src/test/java/com/example/WebTestClientTests.java deleted file mode 100644 index 9e4cfc703..000000000 --- a/spring-cloud-function-samples/function-sample/src/test/java/com/example/WebTestClientTests.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.example; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.web.reactive.server.WebTestClient; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.util.ArrayList; -import java.util.List; - -@FunctionalSpringBootTest -@AutoConfigureWebTestClient -public class WebTestClientTests { - - @Autowired - private WebTestClient client; - - @Test - public void uppercase() { - client.post().uri("/uppercase").body(Mono.just("foo"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("FOO"); - } - - @Test - public void lowercase() { - client.post().uri("/lowercase").body(Flux.just("FOO", "BAR"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("[\"foobar\"]"); - } - - @Test - public void lowercaseMulti() { - client.post().uri("/lowercase").contentType(MediaType.APPLICATION_JSON).body(Mono.just("[\"FOO\"]"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("[\"foo\"]"); - } - - @Test - public void testCollection() { - client.post().uri("/lowercase").contentType(MediaType.APPLICATION_JSON).body(Mono.just("[\"FOO\", \"BAR\"]"), String.class) - .exchange().expectBody(String.class).isEqualTo("[\"foo\",\"bar\"]"); - } - -} diff --git a/spring-cloud-function-samples/pom.xml b/spring-cloud-function-samples/pom.xml deleted file mode 100644 index 6a9b3cff4..000000000 --- a/spring-cloud-function-samples/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-samples - Spring Cloud Function Samples - pom - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - function-sample - function-sample-pof - function-sample-pojo - function-sample-aws - function-functional-sample-aws - function-sample-aws-routing - function-sample-aws-custom - function-sample-aws-custom-bean - function-sample-supplier-exporter - function-sample-azure - function-sample-spring-integration - function-sample-gcp-http - function-sample-gcp-background - function-sample-cloudevent - function-sample-cloudevent-stream - function-sample-cloudevent-rsocket - function-sample-cloudevent-sdk - function-sample-kotlin-web - function-sample-grpc-cloudevent - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - - - - 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 - - - - diff --git a/spring-cloud-function-web/.jdk8 b/spring-cloud-function-web/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-web/pom.xml b/spring-cloud-function-web/pom.xml deleted file mode 100644 index f070fd462..000000000 --- a/spring-cloud-function-web/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - 4.0.0 - - spring-cloud-function-web - jar - Spring Cloud Function Web Support - Spring Cloud Function Web Support - - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - - - - jakarta.servlet - jakarta.servlet-api - provided - - - org.springframework - spring-webmvc - true - - - org.springframework - spring-webflux - true - - - io.projectreactor.netty - reactor-netty - true - - - org.springframework.cloud - spring-cloud-function-context - - - org.springframework.boot - spring-boot-configuration-processor - true - - - commons-logging - commons-logging - 1.2 - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-web - test - - - org.awaitility - awaitility - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - - - diff --git a/spring-cloud-function-web/refactoring_notes b/spring-cloud-function-web/refactoring_notes deleted file mode 100644 index d4b44cad3..000000000 --- a/spring-cloud-function-web/refactoring_notes +++ /dev/null @@ -1,6 +0,0 @@ -If a function returns Flux, we must represent output as JSON Array/Collection since we never know how many elements such flux will contain per each invocation. -For that same reason we can't use TEXT/PLAIN as CT - -NON-WEB -When sendng collection of objects to function who's input is not collection, the inpt will be converted to flux and the result is alos going to be flux. -That is to ensure that the function is invoked with idividual. . . \ No newline at end of file diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/BasicStringConverter.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/BasicStringConverter.java deleted file mode 100644 index e3634fd1c..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/BasicStringConverter.java +++ /dev/null @@ -1,53 +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.web; - -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; - -/** - * Simple implementation of a {@link StringConverter}. - * - * @author Dave Syer - */ -public class BasicStringConverter implements StringConverter { - - private ConversionService conversionService; - - private ConfigurableListableBeanFactory registry; - - public BasicStringConverter(ConfigurableListableBeanFactory registry) { - this.registry = registry; - } - - @Override - public Object convert(Object function, String value) { - if (this.conversionService == null && this.registry != null) { - ConversionService conversionService = this.registry.getConversionService(); - this.conversionService = conversionService != null ? conversionService - : new DefaultConversionService(); - } - //Class type = this.inspector.getInputType(function); - Class type = function == null ? Object.class : FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(((FunctionInvocationWrapper) function).getInputType())); - return this.conversionService.canConvert(String.class, type) - ? this.conversionService.convert(value, type) : value; - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionHttpProperties.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionHttpProperties.java deleted file mode 100644 index c6b9bd87a..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/FunctionHttpProperties.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2023-2023 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 org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.function.context.FunctionProperties; - -/** -* -* @author Oleg Zhurakousky -* @since 4.0.4 -* -*/ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX + ".http") -public class FunctionHttpProperties { - - /** - * Function definition mappings for GET method (e.g. 'spring.cloud.function.http.GET=foo;bar|baz') - */ - public String get; - - - /** - * Function definition mappings for POST method (e.g. 'spring.cloud.function.http.POST=foo;bar|baz') - */ - public String post; - - /** - * Function definition mappings for PUT method (e.g. 'spring.cloud.function.http.PUT=foo;bar|baz') - */ - public String put; - - /** - * Function definition mappings for DELETE method (e.g. 'spring.cloud.function.http.DELETE=foo;bar|baz') - */ - public String delete; - - public String getGet() { - return this.get; - } - - public void setGet(String get) { - this.get = get; - } - - public String getPost() { - return post; - } - - public void setPost(String post) { - this.post = post; - } - - public String getPut() { - return put; - } - - public void setPut(String put) { - this.put = put; - } - - public String getDelete() { - return delete; - } - - public void setDelete(String delete) { - this.delete = delete; - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestApplication.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestApplication.java deleted file mode 100644 index 529aded42..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/RestApplication.java +++ /dev/null @@ -1,36 +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.web; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; - -/** - * @author Mark Fisher - */ -// @checkstyle:off -@SpringBootConfiguration(proxyBeanMethods = false) -@EnableAutoConfiguration -public class RestApplication { - - public static void main(String[] args) { - SpringApplication.run(RestApplication.class, args); - } - -} -// @checkstyle:on diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/StringConverter.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/StringConverter.java deleted file mode 100644 index 904476142..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/StringConverter.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.web; - -/** - * @author Dave Syer - * - */ -public interface StringConverter { - - Object convert(Object function, String value); - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/constants/WebRequestConstants.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/constants/WebRequestConstants.java deleted file mode 100644 index 2a73afac5..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/constants/WebRequestConstants.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.web.constants; - -/** - * Common storage for web request attribute names (in a separate package to avoid cycles). - * - * @author Dave Syer - */ -public abstract class WebRequestConstants { - - /** - * Function attribute name. - */ - public static final String FUNCTION = WebRequestConstants.class.getName() - + ".function"; - - /** - * Consumer attribute name. - */ - public static final String CONSUMER = WebRequestConstants.class.getName() - + ".consumer"; - - /** - * Supplier attribute name. - */ - public static final String SUPPLIER = WebRequestConstants.class.getName() - + ".supplier"; - - /** - * Argument attribute name. - */ - public static final String ARGUMENT = WebRequestConstants.class.getName() - + ".argument"; - - /** - * Handler attribute name. - */ - public static final String HANDLER = WebRequestConstants.class.getName() + ".handler"; - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java deleted file mode 100644 index 239ac546e..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionController.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2016-2023 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.flux; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.web.FunctionHttpProperties; -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.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.codec.multipart.FormFieldPart; -import org.springframework.http.codec.multipart.Part; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Dave Syer - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -@Component -@EnableConfigurationProperties(FunctionHttpProperties.class) -public class FunctionController { - - private final FunctionHttpProperties functionHttpProperties; - - public FunctionController(FunctionHttpProperties functionHttpProperties) { - this.functionHttpProperties = functionHttpProperties; - } - - @SuppressWarnings("unchecked") - @PostMapping(path = "/**", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - @ResponseBody - public Mono> form(ServerWebExchange request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return request.getFormData().doOnSuccess(params -> wrapper.getParams().addAll(params)) - .then(Mono.defer(() -> (Mono>) FunctionWebRequestProcessingHelper - .processRequest(wrapper, wrapper.getParams(), false))); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - - } - - @SuppressWarnings("unchecked") - @PostMapping(path = "/**", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseBody - public Mono> multipart(ServerWebExchange request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return request.getMultipartData() - .doOnSuccess(params -> wrapper.getParams().addAll(multi(params))) - .then(Mono.defer(() -> (Mono>) FunctionWebRequestProcessingHelper - .processRequest(wrapper, wrapper.getParams(), false))); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - } - - @SuppressWarnings("unchecked") - @PostMapping(path = "/**") - @ResponseBody - public Mono> post(ServerWebExchange request, - @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return (Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, body, false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - } - - @SuppressWarnings("unchecked") - @PutMapping(path = "/**") - @ResponseBody - public Mono> put(ServerWebExchange request, - @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("PUT", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return (Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, body, false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("PUT", wrapper.getFunction().getFunctionDefinition())); - } - } - - @SuppressWarnings("unchecked") - @DeleteMapping(path = "/**") - @ResponseBody - public Mono> delete(ServerWebExchange request, - @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("DELETE", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return (Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, body, false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("DELETE", wrapper.getFunction().getFunctionDefinition())); - } - } - - @PostMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @ResponseBody - public Publisher postStream(ServerWebExchange request, @RequestBody(required = false) Flux body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return FunctionWebRequestProcessingHelper.processRequest(wrapper, body, true); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - - } - - @GetMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @ResponseBody - public Publisher getStream(ServerWebExchange request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("GET", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getArgument(), true); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("GET", wrapper.getFunction().getFunctionDefinition())); - } - } - - @SuppressWarnings("unchecked") - @GetMapping(path = "/**") - @ResponseBody - public Mono> get(ServerWebExchange request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("GET", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return (Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getArgument(), false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("GET", wrapper.getFunction().getFunctionDefinition())); - } - } - - private FunctionWrapper wrapper(ServerWebExchange request) { - FunctionInvocationWrapper function = (FunctionInvocationWrapper) request - .getAttribute(WebRequestConstants.HANDLER); - HttpHeaders headers = HttpHeaders.writableHttpHeaders(request.getRequest().getHeaders()); - headers.set("uri", request.getRequest().getURI().toString()); - FunctionWrapper wrapper = new FunctionWrapper(function); - wrapper.setHeaders(headers); - wrapper.getParams().addAll(request.getRequest().getQueryParams()); - String argument = (String) request.getAttribute(WebRequestConstants.ARGUMENT); - if (argument != null) { - wrapper.setArgument(argument); - } - return wrapper; - } - - private MultiValueMap multi(MultiValueMap body) { - MultiValueMap map = new LinkedMultiValueMap<>(); - for (String key : body.keySet()) { - for (Part part : body.get(key)) { - if (part instanceof FormFieldPart) { - FormFieldPart form = (FormFieldPart) part; - map.add(key, form.value()); - } - } - } - return map; - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionHandlerMapping.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionHandlerMapping.java deleted file mode 100644 index 579bf3aa1..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/FunctionHandlerMapping.java +++ /dev/null @@ -1,102 +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.web.flux; - - -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.web.constants.WebRequestConstants; -import org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -@Configuration -@ConditionalOnClass(RequestMappingHandlerMapping.class) -public class FunctionHandlerMapping extends RequestMappingHandlerMapping - implements InitializingBean { - - private final FunctionCatalog functions; - - private final FunctionController controller; - - private final FunctionProperties functionProperties; - - @Value("${spring.cloud.function.web.path:}") - private String prefix = ""; - - @Autowired - public FunctionHandlerMapping(FunctionCatalog catalog, - FunctionController controller, FunctionProperties functionProperties) { - this.functions = catalog; - this.logger.info("FunctionCatalog: " + catalog); - setOrder(super.getOrder() - 5); - this.controller = controller; - this.functionProperties = functionProperties; - } - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - detectHandlerMethods(this.controller); - while (this.prefix.endsWith("/")) { - this.prefix = this.prefix.substring(0, this.prefix.length() - 1); - } - } - - @Override - public Mono getHandlerInternal(ServerWebExchange request) { - String path = request.getRequest().getPath().pathWithinApplication().value(); - if (StringUtils.hasText(this.prefix) && !path.startsWith(this.prefix)) { - return Mono.empty(); - } - Mono handler = super.getHandlerInternal(request); - if (path == null) { - return handler; - } - if (path.startsWith(this.prefix)) { - path = path.substring(this.prefix.length()); - } - Object function = FunctionWebRequestProcessingHelper - .findFunction(this.functionProperties, request.getRequest().getMethod(), this.functions, request.getAttributes(), path); - - if (function != null) { - if (this.logger.isDebugEnabled()) { - this.logger.debug("Found function for POST: " + path); - } - request.getAttributes().put(WebRequestConstants.HANDLER, function); - } - Object actual = function; - return handler.filter(method -> actual != null); - } - - @Override - protected void initHandlerMethods() { - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java deleted file mode 100644 index 0aade98bb..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java +++ /dev/null @@ -1,61 +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.web.flux; - -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.web.BasicStringConverter; -import org.springframework.cloud.function.web.StringConverter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler; - -/** - * @author Dave Syer - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class }) -@ConditionalOnWebApplication(type = Type.REACTIVE) -@Import(FunctionController.class) -@AutoConfigureAfter({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class }) -public class ReactorAutoConfiguration { - - @Bean - public FunctionHandlerMapping functionHandlerMapping(FunctionCatalog catalog, FunctionController controller, FunctionProperties functionProperties) { - return new FunctionHandlerMapping(catalog, controller, functionProperties); - } - - @Bean - @ConditionalOnMissingBean - public StringConverter functionStringConverter(ConfigurableListableBeanFactory beanFactory) { - return new BasicStringConverter(beanFactory); - } - -} 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 deleted file mode 100644 index 969ad6ca5..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializer.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2012-2022 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.function; - -import java.lang.management.ManagementFactory; -import java.time.Duration; -import java.util.Collections; -import java.util.Set; -import java.util.function.Function; - -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 reactor.netty.DisposableServer; -import reactor.netty.http.server.HttpServer; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.web.ErrorProperties; -import org.springframework.boot.autoconfigure.web.WebProperties.Resources; -import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler; -import org.springframework.boot.web.reactive.error.DefaultErrorAttributes; -import org.springframework.boot.web.reactive.error.ErrorAttributes; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -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.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; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.event.SmartApplicationListener; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.http.ResponseEntity; -import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.web.reactive.function.server.HandlerStrategies; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder; -import org.springframework.web.server.WebExceptionHandler; -import org.springframework.web.server.adapter.HttpWebHandlerAdapter; -import org.springframework.web.server.adapter.WebHttpHandlerBuilder; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.ServerResponse.status; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 2.0 - */ -public class FunctionEndpointInitializer implements ApplicationContextInitializer { - - private static boolean webflux = ClassUtils - .isPresent("org.springframework.web.reactive.function.server.RouterFunction", null); - - @Override - public void initialize(GenericApplicationContext context) { - if (webflux && ContextFunctionCatalogInitializer.enabled - && context.getEnvironment().getProperty(FunctionalSpringApplication.SPRING_WEB_APPLICATION_TYPE, - WebApplicationType.class, WebApplicationType.REACTIVE) == WebApplicationType.REACTIVE - && context.getEnvironment().getProperty("spring.functional.enabled", Boolean.class, false)) { - registerEndpoint(context); - registerWebFluxAutoConfiguration(context); - } - } - - private void registerWebFluxAutoConfiguration(GenericApplicationContext context) { - context.registerBean(DefaultErrorWebExceptionHandler.class, () -> errorHandler(context)); - context.registerBean(WebHttpHandlerBuilder.WEB_HANDLER_BEAN_NAME, HttpWebHandlerAdapter.class, - () -> httpHandler(context)); - context.addApplicationListener(new ServerListener(context)); - } - - private void registerEndpoint(GenericApplicationContext context) { - context.registerBean(FunctionEndpointFactory.class, - () -> new FunctionEndpointFactory(context.getBean(FunctionProperties.class), context.getBean(FunctionCatalog.class), - context.getEnvironment())); - RouterFunctionRegister.register(context); - } - - private HttpWebHandlerAdapter httpHandler(GenericApplicationContext context) { - return (HttpWebHandlerAdapter) RouterFunctions.toHttpHandler(context.getBean(RouterFunction.class), - HandlerStrategies.empty().exceptionHandler(context.getBeansOfType(WebExceptionHandler.class).values().iterator().next()) - .codecs(config -> config.registerDefaults(true)).build()); - } - - private DefaultErrorWebExceptionHandler errorHandler(GenericApplicationContext context) { - context.registerBean(ErrorAttributes.class, () -> new DefaultErrorAttributes()); - context.registerBean(ErrorProperties.class, () -> new ErrorProperties()); - - context.registerBean(Resources.class, () -> new Resources()); - DefaultErrorWebExceptionHandler handler = new DefaultErrorWebExceptionHandler( - context.getBeansOfType(ErrorAttributes.class).values().iterator().next(), context.getBean(Resources.class), - context.getBean(ErrorProperties.class), context); - ServerCodecConfigurer codecs = ServerCodecConfigurer.create(); - handler.setMessageWriters(codecs.getWriters()); - handler.setMessageReaders(codecs.getReaders()); - return handler; - } - - private static class RouterFunctionRegister { - - private static void register(GenericApplicationContext context) { - context.registerBean(RouterFunction.class, - () -> context.getBean(FunctionEndpointFactory.class).functionEndpoints()); - } - - } - - private static class ServerListener implements SmartApplicationListener { - - private static Log logger = LogFactory.getLog(ServerListener.class); - - private GenericApplicationContext context; - - ServerListener(GenericApplicationContext context) { - this.context = context; - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { - ApplicationContext context = ((ContextRefreshedEvent) event).getApplicationContext(); - if (context != this.context) { - return; - } - if (!ClassUtils.isPresent("org.springframework.http.server.reactive.HttpHandler", null)) { - logger.info("No web server classes found so no server to start"); - return; - } - Integer port = Integer.valueOf(context.getEnvironment().resolvePlaceholders("${server.port:${PORT:8080}}")); - String address = context.getEnvironment().resolvePlaceholders("${server.address:0.0.0.0}"); - if (port >= 0) { - HttpHandler handler = context.getBeansOfType(HttpHandler.class).values().iterator().next(); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler); - HttpServer httpServer = HttpServer.create().host(address).port(port).handle(adapter); - Thread thread = new Thread( - () -> httpServer.bindUntilJavaShutdown(Duration.ofSeconds(60), (server) -> callback(server, context)), - "server-startup"); - thread.setDaemon(false); - thread.start(); - } - } - - private void callback(DisposableServer server, ApplicationContext context) { - logger.info("HTTP server started on port: " + server.port()); - if (context instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) context).getEnvironment().getPropertySources().addFirst( - new MapPropertySource("functionalServerProps", Collections.singletonMap("local.server.port", server.port()))); - } - try { - double uptime = ManagementFactory.getRuntimeMXBean().getUptime(); - logger.info("JVM running for " + uptime + "ms"); - } - catch (Throwable e) { - // ignore - } - } - - @Override - public boolean supportsEventType(Class eventType) { - return eventType.isAssignableFrom(ContextRefreshedEvent.class); - } - - } - -} - -class FunctionEndpointFactory { - - private static Log logger = LogFactory.getLog(FunctionEndpointFactory.class); - - private final FunctionCatalog functionCatalog; - - private final String handler; - - private final FunctionProperties functionProperties; - - FunctionEndpointFactory(FunctionProperties functionProperties, FunctionCatalog functionCatalog, Environment environment) { - String handler = environment.resolvePlaceholders("${function.handler}"); - if (handler.startsWith("$")) { - handler = null; - } - this.functionCatalog = functionCatalog; - this.handler = handler; - this.functionProperties = functionProperties; - } - - private FunctionInvocationWrapper extract(ServerRequest request) { - FunctionInvocationWrapper function; - if (handler != null) { - logger.info("Configured function: " + handler); - Set names = this.functionCatalog.getNames(Function.class); - Assert.isTrue(names.contains(handler), "Cannot locate function: " + handler); - function = this.functionCatalog.lookup(Function.class, handler); - } - else { - function = FunctionWebRequestProcessingHelper.findFunction(this.functionProperties, request.method(), functionCatalog, request.attributes(), - request.path()); - } - return function; - } - - @SuppressWarnings({ "unchecked" }) - public RouterFunction functionEndpoints() { - return route(POST("/**"), request -> { - FunctionInvocationWrapper funcWrapper = extract(request); - Class outputType = funcWrapper == null ? Object.class - : FunctionTypeUtils.getRawType(FunctionTypeUtils.getGenericType(funcWrapper.getOutputType())); - FunctionWrapper wrapper = new FunctionWrapper(funcWrapper); - Mono> stream = request.bodyToMono(String.class) - .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 - return builder.build(); - } - else { - return builder.body(entity != null && entity.hasBody() ? Mono.just((T) entity.getBody()) : Mono.empty(), outputType); - } - }); - }).andRoute(GET("/**"), request -> { - FunctionInvocationWrapper funcWrapper = extract(request); - Class outputType = FunctionTypeUtils - .getRawType(FunctionTypeUtils.getGenericType(funcWrapper.getOutputType())); - if (funcWrapper.isSupplier()) { - Object result = FunctionWebRequestProcessingHelper.invokeFunction(funcWrapper, null, funcWrapper.isInputTypeMessage()); - if (!(result instanceof Publisher)) { - result = Mono.just(result); - } - return ServerResponse.ok().body(result, outputType); - } - else { - FunctionWrapper wrapper = new FunctionWrapper(funcWrapper); - - wrapper.setHeaders(request.headers().asHttpHeaders()); - String argument = (String) request.attribute(WebRequestConstants.ARGUMENT).get(); - 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/FunctionController.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionController.java deleted file mode 100644 index 0e5977e7b..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionController.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2016-2023 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.mvc; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.web.FunctionHttpProperties; -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.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.ResponseEntity.BodyBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.context.request.ServletWebRequest; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; - -/** - * @author Dave Syer - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -@Component -@EnableConfigurationProperties(FunctionHttpProperties.class) -public class FunctionController { - - private final FunctionHttpProperties functionHttpProperties; - - public FunctionController(FunctionHttpProperties functionHttpProperties) { - this.functionHttpProperties = functionHttpProperties; - } - - @PostMapping(path = "/**", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE, - MediaType.MULTIPART_FORM_DATA_VALUE }) - @ResponseBody - public Object form(WebRequest request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - if (((ServletWebRequest) request).getRequest() instanceof StandardMultipartHttpServletRequest) { - MultiValueMap multiFileMap = ((StandardMultipartHttpServletRequest) ((ServletWebRequest) request) - .getRequest()).getMultiFileMap(); - if (!CollectionUtils.isEmpty(multiFileMap)) { - List> files = multiFileMap.values().stream().flatMap(v -> v.stream()) - .map(file -> MessageBuilder.withPayload(file).copyHeaders(wrapper.getHeaders()).build()) - .collect(Collectors.toList()); - FunctionInvocationWrapper function = wrapper.getFunction(); - - Publisher result = (Publisher) function.apply(Flux.fromIterable(files)); - BodyBuilder builder = ResponseEntity.ok(); - if (result instanceof Flux) { - result = Flux.from(result).map(message -> { - return message instanceof Message ? ((Message) message).getPayload() : message; - }).collectList(); - } - return Mono.from(result).flatMap(body -> Mono.just(builder.body(body))); - } - } - return FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getParams(), false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - } - - @SuppressWarnings("unchecked") - @PostMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @ResponseBody - public Mono>> postStream(WebRequest request, - @RequestBody(required = false) String body) { - String argument = StringUtils.hasText(body) ? body : ""; - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return ((Mono>) FunctionWebRequestProcessingHelper.processRequest(wrapper, argument, true)).map(response -> ResponseEntity.ok() - .headers(response.getHeaders()).body((Publisher) response.getBody())); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - } - - @GetMapping(path = "/**", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @ResponseBody - public Publisher getStream(WebRequest request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("GET", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getArgument(), true); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("GET", wrapper.getFunction().getFunctionDefinition())); - } - } - - @PostMapping(path = "/**") - @ResponseBody - public Object post(WebRequest request, @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("POST", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - Assert.isTrue(!wrapper.getFunction().isSupplier(), "'POST' can only be mapped to Function or Consumer"); - return FunctionWebRequestProcessingHelper.processRequest(wrapper, body, false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("POST", wrapper.getFunction().getFunctionDefinition())); - } - } - - @PutMapping(path = "/**") - @ResponseBody - public Object put(WebRequest request, @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("PUT", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return FunctionWebRequestProcessingHelper.processRequest(wrapper, body, false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("PUT", wrapper.getFunction().getFunctionDefinition())); - } - } - - @DeleteMapping(path = "/**") - @ResponseStatus(HttpStatus.NO_CONTENT) - public void delete(WebRequest request, @RequestBody(required = false) String body) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("DELETE", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - Assert.isTrue(wrapper.getFunction().isConsumer(), "'DELETE' can only be mapped to Consumer"); - FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getArgument(), false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("DELETE", wrapper.getFunction().getFunctionDefinition())); - } - } - - @GetMapping(path = "/**") - @ResponseBody - public Object get(WebRequest request) { - FunctionWrapper wrapper = wrapper(request); - if (FunctionWebRequestProcessingHelper.isFunctionValidForMethod("GET", wrapper.getFunction().getFunctionDefinition(), this.functionHttpProperties)) { - return FunctionWebRequestProcessingHelper.processRequest(wrapper, wrapper.getArgument(), false); - } - else { - throw new IllegalArgumentException(FunctionWebRequestProcessingHelper.buildBadMappingErrorMessage("GET", wrapper.getFunction().getFunctionDefinition())); - } - } - - private FunctionWrapper wrapper(WebRequest request) { - FunctionInvocationWrapper function = (FunctionInvocationWrapper) request - .getAttribute(WebRequestConstants.HANDLER, WebRequest.SCOPE_REQUEST); - FunctionWrapper wrapper = new FunctionWrapper(function, (((ServletWebRequest) request).getRequest()).getMethod()); - for (String key : request.getParameterMap().keySet()) { - wrapper.getParams().addAll(key, Arrays.asList(request.getParameterValues(key))); - } - for (Iterator keys = request.getHeaderNames(); keys.hasNext();) { - String key = keys.next(); - wrapper.getHeaders().addAll(key, Arrays.asList(request.getHeaderValues(key))); - } - - HttpHeaders headers = HttpHeaders.writableHttpHeaders(wrapper.getHeaders()); - headers.set("uri", ((ServletWebRequest) request).getRequest().getRequestURI()); - - String argument = (String) request.getAttribute(WebRequestConstants.ARGUMENT, - WebRequest.SCOPE_REQUEST); - if (argument != null) { - wrapper.setArgument(argument); - } - return wrapper; - } -} 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 deleted file mode 100644 index 5ad188ea3..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java +++ /dev/null @@ -1,126 +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.web.mvc; - -import java.util.HashMap; - -import jakarta.servlet.http.HttpServletRequest; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.web.constants.WebRequestConstants; -import org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.util.StringUtils; -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 - */ -@Configuration -@ConditionalOnClass(RequestMappingHandlerMapping.class) -public class FunctionHandlerMapping extends RequestMappingHandlerMapping - implements InitializingBean { - - private final FunctionCatalog functions; - - private final FunctionController controller; - - private final FunctionProperties functionProperties; - - @Value("${spring.cloud.function.web.path:}") - private String prefix = ""; - - @Autowired - public FunctionHandlerMapping(FunctionProperties functionProperties, FunctionCatalog catalog, - FunctionController controller) { - this.functions = catalog; - this.logger.info("FunctionCatalog: " + catalog); - setOrder(super.getOrder() - 5); - this.controller = controller; - this.functionProperties = functionProperties; - } - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - detectHandlerMethods(this.controller); - while (this.prefix.endsWith("/")) { - this.prefix = this.prefix.substring(0, this.prefix.length() - 1); - } - } - - @Override - protected void initHandlerMethods() { - } - - @Override - protected HandlerMethod getHandlerInternal(HttpServletRequest request) - throws Exception { - HandlerMethod handler = super.getHandlerInternal(request); - if (handler == null) { - return null; - } - String path = (String) request - .getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); - if (path == null) { - return handler; - } - if (StringUtils.hasText(this.prefix) && !path.startsWith(this.prefix)) { - return null; - } - if (path.startsWith(this.prefix)) { - path = path.substring(this.prefix.length()); - } - - Object function = FunctionWebRequestProcessingHelper.findFunction(this.functionProperties, HttpMethod.valueOf(request.getMethod()), - this.functions, new HttpRequestAttributeDelegate(request), path); - if (function != null) { - if (this.logger.isDebugEnabled()) { - this.logger.debug("Found function for GET: " + path); - } - request.setAttribute(WebRequestConstants.HANDLER, function); - return handler; - } - return null; - } - - @SuppressWarnings("serial") - private static class HttpRequestAttributeDelegate extends HashMap { - private final HttpServletRequest request; - HttpRequestAttributeDelegate(HttpServletRequest request) { - this.request = request; - } - - @Override - public Object put(String key, Object value) { - this.request.setAttribute(key, value); - return value; - } - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/ReactorAutoConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/ReactorAutoConfiguration.java deleted file mode 100644 index 4c9666f55..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/ReactorAutoConfiguration.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-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.web.mvc; - -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.web.BasicStringConverter; -import org.springframework.cloud.function.web.StringConverter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler; - -/** - * @author Dave Syer - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnWebApplication(type = Type.SERVLET) -@ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class }) -@Import({ FunctionController.class}) -public class ReactorAutoConfiguration { - - @Bean - public FunctionHandlerMapping functionHandlerMapping(FunctionProperties functionProperties, FunctionCatalog catalog, FunctionController controller) { - return new FunctionHandlerMapping(functionProperties, catalog, controller); - } - - @Bean - @ConditionalOnMissingBean - public StringConverter functionStringConverter(ConfigurableListableBeanFactory beanFactory) { - return new BasicStringConverter(beanFactory); - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/DestinationResolver.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/DestinationResolver.java deleted file mode 100644 index 3479e49a4..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/DestinationResolver.java +++ /dev/null @@ -1,29 +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.web.source; - -import java.util.function.Supplier; - -/** - * @author Dave Syer - * - */ -public interface DestinationResolver { - - String destination(Supplier supplier, String name, Object value); - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/ExporterProperties.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/ExporterProperties.java deleted file mode 100644 index a7c32f9bb..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/ExporterProperties.java +++ /dev/null @@ -1,187 +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.web.source; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.function.context.FunctionProperties; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -@ConfigurationProperties(prefix = FunctionProperties.PREFIX + ".web.export") -public class ExporterProperties { - - /** - * Flag to indicate that the supplier emits HTTP requests automatically on startup. - */ - private boolean autoStartup = true; - - /** - * Flag to indicate that extra logging is required for the supplier. - */ - private boolean debug = true; - - /** - * Properties related to a source of items (via an HTTP GET on startup). - */ - private Source source = new Source(); - - /** - * Properties related to a sink of items (via an HTTP POST on startup). - */ - private Sink sink = new Sink(); - - /** - * Flag to enable the export of a supplier. - */ - private boolean enabled; - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isAutoStartup() { - return this.autoStartup; - } - - public void setAutoStartup(boolean autoStartup) { - this.autoStartup = autoStartup; - } - - public boolean isDebug() { - return this.debug; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - public Source getSource() { - return this.source; - } - - public Sink getSink() { - return this.sink; - } - - public static class Source { - - /** - * URL template for creating a virtual Supplier from HTTP GET. - */ - private String url; - - /** - * If the origin url is set, the type of content expected (e.g. a POJO class). - * Defaults to String. - */ - private Class type; - - /** - * Include the incoming headers in the outgoing Supplier. If true the supplier - * will be of generic type Message of T equal to the source type. - */ - private boolean includeHeaders = true; - - public String getUrl() { - return this.url; - } - - public void setUrl(String url) { - this.url = url; - } - - public Class getType() { - return this.type == null ? String.class : this.type; - } - - public void setType(Class type) { - this.type = type; - } - - public void setIncludeHeaders(boolean includeHeaders) { - this.includeHeaders = includeHeaders; - } - - public boolean isIncludeHeaders() { - return this.includeHeaders; - } - - } - - public static class Sink { - - /** - * URL template for outgoing HTTP requests. Each item from the supplier is POSTed - * to this target. - */ - private String url; - - /** - * Additional headers to append to the outgoing HTTP requests. - */ - private Map headers = new LinkedHashMap<>(); - - /** - * The name of a specific existing Supplier to export from the function catalog. - */ - private String name; - - /** - * Content type to use when serializing source's output for transport (default 'application/json`). - */ - private String contentType = "application/json"; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return this.url; - } - - public void setUrl(String url) { - this.url = url; - } - - public Map getHeaders() { - return this.headers; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - } - -} 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 deleted file mode 100644 index 9d65de859..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterAutoConfiguration.java +++ /dev/null @@ -1,116 +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.web.source; - -import java.lang.reflect.Type; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; -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.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.web.source.FunctionExporterAutoConfiguration.SourceActiveCondition; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.ResolvableType; -import org.springframework.core.env.Environment; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * @author Dave Syer - * - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass(WebClient.class) -@Conditional(SourceActiveCondition.class) -@EnableConfigurationProperties(ExporterProperties.class) -public class FunctionExporterAutoConfiguration { - - private ExporterProperties props; - - @Autowired - FunctionExporterAutoConfiguration(ExporterProperties props) { - this.props = props; - } - - @Bean - @ConditionalOnProperty(prefix = "spring.cloud.function.web.export.sink", name = "url") - public SupplierExporter sourceForwarder(RequestBuilder requestBuilder, DestinationResolver destinationResolver, - FunctionCatalog catalog, WebClient.Builder builder) { - return new SupplierExporter(requestBuilder, destinationResolver, catalog, builder.build(), this.props); - } - - @Bean - @ConditionalOnProperty(prefix = "spring.cloud.function.web.export.source", name = "url") - public FunctionRegistration>> origin(WebClient.Builder builder) { - HttpSupplier supplier = new HttpSupplier(builder.build(), this.props); - 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(); -// } - Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(HttpSupplier.class); - registration = registration.type(type); - return registration; - } - - @Bean - public RequestBuilder simpleRequestBuilder(Environment environment) { - SimpleRequestBuilder builder = new SimpleRequestBuilder(environment); - if (this.props.getSink().getUrl() != null) { - builder.setTemplateUrl(this.props.getSink().getUrl()); - } - builder.setHeaders(this.props.getSink().getHeaders()); - return builder; - } - - @Bean - @ConditionalOnMissingBean - public DestinationResolver simpleDestinationResolver() { - return new SimpleDestinationResolver(); - } - - static class SourceActiveCondition extends AnyNestedCondition { - - SourceActiveCondition() { - super(ConfigurationPhase.PARSE_CONFIGURATION); - } - - @ConditionalOnNotWebApplication - static class OnNotWebapp { - - } - - @ConditionalOnProperty(prefix = "spring.cloud.function.web.export", name = "enabled", matchIfMissing = true) - static class Enabled { - - } - - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterInitializer.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterInitializer.java deleted file mode 100644 index 41e906d1d..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/FunctionExporterInitializer.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.web.source; - -import java.util.function.Supplier; - -import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebEnvironment; -import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.util.ClassUtils; -import org.springframework.web.context.ConfigurableWebEnvironment; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClient.Builder; - -/** - * @author Dave Syer - * @since 2.0 - * - */ -class FunctionExporterInitializer implements ApplicationContextInitializer { - - @Override - public void initialize(GenericApplicationContext context) { - if (ContextFunctionCatalogInitializer.enabled - && context.getEnvironment().getProperty("spring.functional.enabled", Boolean.class, false) - && isExporting(context)) { - registerWebClient(context); - registerExport(context); - } - } - - private void registerWebClient(GenericApplicationContext context) { - if (ClassUtils.isPresent("org.springframework.web.reactive.function.client.WebClient", - getClass().getClassLoader())) { - if (context.getBeanFactory().getBeanNamesForType(WebClient.Builder.class, false, false).length == 0) { - context.registerBean(WebClient.Builder.class, new Supplier() { - @Override - public Builder get() { - return WebClient.builder(); - } - }); - } - } - } - - private boolean isExporting(GenericApplicationContext context) { - Boolean enabled = context.getEnvironment().getProperty("spring.cloud.function.web.export.enabled", - Boolean.class); - if (enabled != null) { - return enabled; - } - if (ClassUtils.isPresent("org.springframework.web.context.WebApplicationContext", - getClass().getClassLoader())) { - if (context instanceof WebApplicationContext || context instanceof ReactiveWebApplicationContext - || context.getEnvironment() instanceof ConfigurableWebEnvironment - || context.getEnvironment() instanceof ConfigurableReactiveWebEnvironment) { - return false; - } - } - return true; - } - - private void registerExport(GenericApplicationContext context) { - context.registerBean(ExporterProperties.class, () -> new ExporterProperties()); - context.registerBean(FunctionExporterAutoConfiguration.class, - () -> new FunctionExporterAutoConfiguration(context.getBean(ExporterProperties.class))); - if (context.getBeanFactory().getBeanNamesForType(DestinationResolver.class, false, false).length == 0) { - context.registerBean(DestinationResolver.class, - () -> context.getBean(FunctionExporterAutoConfiguration.class).simpleDestinationResolver()); - } - if (context.getBeanFactory().getBeanNamesForType(RequestBuilder.class, false, false).length == 0) { - context.registerBean(RequestBuilder.class, () -> context.getBean(FunctionExporterAutoConfiguration.class) - .simpleRequestBuilder(context.getEnvironment())); - } - if (context.getEnvironment().getProperty("spring.cloud.function.web.export.source.url") != null) { - context.registerBean("origin", FunctionRegistration.class, () -> context - .getBean(FunctionExporterAutoConfiguration.class).origin(context.getBean(WebClient.Builder.class))); - } - if (context.getEnvironment().getProperty("spring.cloud.function.web.export.sink.url") != null) { - context.registerBean(SupplierExporter.class, - () -> context.getBean(FunctionExporterAutoConfiguration.class).sourceForwarder( - context.getBean(RequestBuilder.class), context.getBean(DestinationResolver.class), - context.getBean(FunctionCatalog.class), context.getBean(WebClient.Builder.class))); - } - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/HttpSupplier.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/HttpSupplier.java deleted file mode 100644 index e22ad1929..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/HttpSupplier.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2018-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.web.source; - -import java.time.Duration; -import java.util.function.Supplier; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.function.web.util.HeaderUtils; -import org.springframework.http.HttpStatusCode; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * A {@link Supplier} that pulls data from an HTTP endpoint. Repeatedly polls the endpoint - * until a non-2xx response is received, at which point it will repeatedly produced a - * Mono at 1 sec intervals until the next 2xx response. - * - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class HttpSupplier implements Supplier> { - - private static Log logger = LogFactory.getLog(HttpSupplier.class); - - private WebClient client; - - private ExporterProperties props; - - /** - * @param client the WebClient to use. The baseUrl should be set. - * @param props the ExporterProperties to use to parameterize the requests. - */ - public HttpSupplier(WebClient client, ExporterProperties props) { - this.client = client; - this.props = props; - } - - @Override - public Flux get() { - return get(this.client); - } - - private Flux get(WebClient client) { - Flux result = client.get().uri(this.props.getSource().getUrl()).exchange() - .flatMap(this::transform).repeat(); - if (this.props.isDebug()) { - result = result.log(); - } - return result.onErrorResume(TerminateException.class, error -> Mono.empty()); - } - - private Mono transform(ClientResponse response) { - HttpStatusCode status = response.statusCode(); - if (!status.is2xxSuccessful()) { - if (this.props.isDebug()) { - logger.info("Delaying supplier based on status=" + response.statusCode()); - } - return Mono.delay(Duration.ofSeconds(1)); - } - return response.bodyToMono(this.props.getSource().getType()) - .map(value -> message(response, value)); - } - - private Object message(ClientResponse response, Object payload) { - if (!this.props.getSource().isIncludeHeaders()) { - return payload; - } - return MessageBuilder.withPayload(payload) - .copyHeaders(HeaderUtils.fromHttp( - HeaderUtils.sanitize(response.headers().asHttpHeaders()))) - .setHeader("scf-sink-url", this.props.getSink().getUrl()) - .setHeader("scf-func-name", this.props.getSink().getName()) - .build(); - } - - @SuppressWarnings("serial") - private static class TerminateException extends RuntimeException { - - @SuppressWarnings("unused") - TerminateException() { - super("Planned termination"); - } - - @Override - public synchronized Throwable fillInStackTrace() { - return this; - } - - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/RequestBuilder.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/RequestBuilder.java deleted file mode 100644 index cb0dd48cd..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/RequestBuilder.java +++ /dev/null @@ -1,33 +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.web.source; - -import java.net.URI; - -import org.springframework.http.HttpHeaders; - -/** - * @author Dave Syer - * - */ -public interface RequestBuilder { - - URI uri(String destination); - - HttpHeaders headers(String destination, Object value); - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleDestinationResolver.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleDestinationResolver.java deleted file mode 100644 index 3426c757c..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleDestinationResolver.java +++ /dev/null @@ -1,32 +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.web.source; - -import java.util.function.Supplier; - -/** - * @author Dave Syer - * - */ -public class SimpleDestinationResolver implements DestinationResolver { - - @Override - public String destination(Supplier supplier, String name, Object value) { - return name.contains("|") ? name.substring(0, name.indexOf("|")).trim() : name; - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleRequestBuilder.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleRequestBuilder.java deleted file mode 100644 index abc3f600f..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SimpleRequestBuilder.java +++ /dev/null @@ -1,83 +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.web.source; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.cloud.function.web.util.HeaderUtils; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; - -/** - * @author Dave Syer - * - */ -class SimpleRequestBuilder implements RequestBuilder { - - private String baseUrl = "http://${destination}"; - - private Map headers = new LinkedHashMap<>(); - - private Environment environment; - - SimpleRequestBuilder(Environment environment) { - this.environment = environment; - } - - @Override - public HttpHeaders headers(String destination, Object value) { - MessageHeaders incoming = new MessageHeaders(Collections.emptyMap()); - if (value instanceof Message) { - Message message = (Message) value; - incoming = message.getHeaders(); - } - HttpHeaders result = HeaderUtils.fromMessage(incoming); - for (String key : this.headers.keySet()) { - String header = this.headers.get(key); - header = header.replace("${destination}", destination); - header = this.environment.resolvePlaceholders(header); - result.set(key, header); - } - return result; - } - - @Override - public URI uri(String destination) { - try { - return new URI(this.baseUrl.replace("${destination}", destination) - .replace("{{destination}}", destination)); - } - catch (URISyntaxException e) { - throw new IllegalStateException("Cannot create URI", e); - } - } - - public void setTemplateUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - public void setHeaders(Map headers) { - this.headers.putAll(headers); - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java deleted file mode 100644 index 8a24e8455..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/source/SupplierExporter.java +++ /dev/null @@ -1,214 +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.web.source; - -import java.net.URI; -import java.time.Duration; -import java.util.Collections; -import java.util.Set; -import java.util.function.Supplier; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.Disposable; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.util.retry.Retry; - -import org.springframework.cloud.function.context.FunctionCatalog; -import org.springframework.context.SmartLifecycle; -import org.springframework.http.HttpHeaders; -import org.springframework.messaging.Message; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * Forwards items obtained from a {@link Supplier} or set of suppliers to an external HTTP - * endpoint. - * - * @author Dave Syer - * @author Oleg Zhurakousky - * - */ -public class SupplierExporter implements SmartLifecycle { - - private static Log logger = LogFactory.getLog(SupplierExporter.class); - - private final FunctionCatalog catalog; - - private final WebClient client; - - private final DestinationResolver destinationResolver; - - private final RequestBuilder requestBuilder; - - private final String supplier; - - private final String contentType; - - private volatile boolean running; - - private volatile boolean ok = true; - - private boolean autoStartup = true; - - private boolean debug = true; - - private volatile Disposable subscription; - - SupplierExporter(RequestBuilder requestBuilder, - DestinationResolver destinationResolver, FunctionCatalog catalog, - WebClient client, ExporterProperties exporterProperties) { - this.requestBuilder = requestBuilder; - this.destinationResolver = destinationResolver; - this.catalog = catalog; - this.client = client; - this.debug = exporterProperties.isDebug(); - this.autoStartup = exporterProperties.isAutoStartup(); - this.supplier = exporterProperties.getSink().getName(); - this.contentType = exporterProperties.getSink().getContentType(); - } - - @Override - public void start() { - if (this.running) { - return; - } - logger.info("Starting"); - - Flux streams = Flux.empty(); - Set names = this.supplier == null ? this.catalog.getNames(Supplier.class) - : Collections.singleton(this.supplier); - - boolean suppliersPresent = false; - for (String name : names) { - Supplier> supplier = this.catalog.lookup(name, this.contentType); - if (supplier == null) { - logger.warn("No such Supplier: " + name); - continue; - } - streams = streams.mergeWith(forward(supplier, name)); - suppliersPresent = true; - } - if (suppliersPresent) { - this.subscription = streams - .retryWhen(Retry.backoff(5, Duration.ofSeconds(1))) -// .retry(error -> { -// /* -// * The ConnectException may happen if a server is not yet available/reachable -// * The ClassCast is to handle delayed Mono issued by HttpSupplier.transform for non-2xx responses -// */ -// boolean retry = error instanceof ConnectException || error instanceof ClassCastException -// && this.running; -// if (!retry) { -// this.ok = false; -// if (!this.debug) { -// logger.info(error); -// } -// stop(); -// } -// return retry; -// } -// ) - .doOnComplete(() -> { - stop(); - }) - .subscribe(); - - this.ok = true; - this.running = true; - } - } - - public boolean isOk() { - return this.ok; - } - - @Override - public void stop() { - logger.info("Stopping"); - this.running = false; - this.subscription.dispose(); - } - - @Override - public boolean isRunning() { - return this.running; - } - - @Override - public int getPhase() { - return 0; - } - - @Override - public boolean isAutoStartup() { - return this.autoStartup; - } - - @Override - public void stop(Runnable callback) { - stop(); - callback.run(); - } - - private Flux forward(Supplier> supplier, String name) { - Flux o = (Flux) supplier.get(); -// o.subscribe(v -> { -// System.out.println(v); -// }); - return Flux.from(o).flatMap(value -> { - String destination = this.destinationResolver.destination(supplier, name, value); - if (this.debug) { - logger.info("Posting to: " + destination); - } - return post(uri(destination), destination, value); - }); - } - - private Mono post(URI uri, String destination, Object value) { - Object body = value; - if (value instanceof Message) { - Message message = (Message) value; - body = message.getPayload(); - } - if (this.debug) { - logger.debug("Sending BODY as type: " + body.getClass().getName()); - } - Mono result = this.client.post().uri(uri) - .headers(headers -> headers(headers, destination, value)).bodyValue(body) - .exchange() - .doOnNext(response -> { - if (this.debug) { - logger.debug("Response STATUS: " + response.statusCode()); - } - }); - if (this.debug) { - result = result.log(); - } - return result; - } - - private void headers(HttpHeaders headers, String destination, Object value) { - headers.putAll(this.requestBuilder.headers(destination, value)); - } - - private URI uri(String destination) { - return this.requestBuilder.uri(destination); - } -} 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 deleted file mode 100644 index 2f92cb1b8..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWebRequestProcessingHelper.java +++ /dev/null @@ -1,249 +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.web.util; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -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.cloud.function.context.FunctionCatalog; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.cloud.function.web.FunctionHttpProperties; -import org.springframework.cloud.function.web.constants.WebRequestConstants; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.http.ResponseEntity.BodyBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * !INTERNAL USE ONLY! - * - * @author Oleg Zhurakousky - * - */ -public final class FunctionWebRequestProcessingHelper { - - private static Log logger = LogFactory.getLog(FunctionWebRequestProcessingHelper.class); - - private FunctionWebRequestProcessingHelper() { - - } - - public static FunctionInvocationWrapper findFunction(FunctionProperties functionProperties, HttpMethod method, FunctionCatalog functionCatalog, - Map attributes, String path) { - if (method.equals(HttpMethod.GET) || method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE)) { - return doFindFunction(functionProperties.getDefinition(), method, functionCatalog, attributes, path); - } - else { - throw new IllegalStateException("HTTP method '" + method + "' is not supported;"); - } - } - - public static Object invokeFunction(FunctionInvocationWrapper function, Object input, boolean isMessage) { - Object result = function.apply(input); - return postProcessResult(result, isMessage); - } - - public static boolean isFunctionValidForMethod(String httpMethod, String functionDefinition, FunctionHttpProperties functionHttpProperties) { - String functionDefinitions = null; - switch (httpMethod) { - case "GET": - functionDefinitions = functionHttpProperties.getGet(); - break; - case "POST": - functionDefinitions = functionHttpProperties.getPost(); - break; - case "PUT": - functionDefinitions = functionHttpProperties.getPut(); - break; - case "DELETE": - functionDefinitions = functionHttpProperties.getDelete(); - break; - default: - return false; - } - if (StringUtils.hasText(functionDefinitions)) { - return Arrays.asList(functionDefinitions.split(";")).contains(functionDefinition); - } - return true; - } - - public static String buildBadMappingErrorMessage(String httpMethod, String functionDefinition) { - return "Function '" + functionDefinition + "' is not eligible to be invoked " - + "via " + httpMethod + " method. This is due to the fact that explicit mappings for " + httpMethod - + " are provided via 'spring.cloud.function.http." + httpMethod + "' property " - + "and this function is not listed there. Either remove all explicit mappings for " + httpMethod + " or add this function to the list of functions " - + "specified in 'spring.cloud.function.http." + httpMethod + "' property."; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Publisher processRequest(FunctionWrapper wrapper, Object argument, boolean eventStream) { - if (argument == null) { - argument = ""; - } - FunctionInvocationWrapper function = wrapper.getFunction(); - - if (function == null) { - return Mono.just(ResponseEntity.notFound().build()); - } - - HttpHeaders headers = wrapper.getHeaders(); - - Message inputMessage = null; - - - MessageBuilder builder = MessageBuilder.withPayload(argument); - if (!CollectionUtils.isEmpty(wrapper.getParams())) { - builder = builder.setHeader(HeaderUtils.HTTP_REQUEST_PARAM, wrapper.getParams().toSingleValueMap()); - } - inputMessage = builder.copyHeaders(headers.toSingleValueMap()).build(); - - if (function.isRoutingFunction()) { - function.setSkipOutputConversion(true); - } - - Object result = function.apply(inputMessage); - if (function.isConsumer()) { - if (result instanceof Publisher) { - Mono.from((Publisher) result).subscribe(); - } - return "DELETE".equals(wrapper.getMethod()) ? - Mono.empty() : Mono.just(ResponseEntity.accepted().headers(HeaderUtils.sanitize(headers)).build()); - } - - BodyBuilder responseOkBuilder = ResponseEntity.ok().headers(HeaderUtils.sanitize(headers)); - - Publisher pResult; - if (result instanceof Publisher) { - pResult = (Publisher) result; - if (eventStream) { - return Flux.from(pResult); - } - - if (pResult instanceof Flux) { - pResult = ((Flux) pResult).onErrorContinue((e, v) -> { - logger.error("Failed to process value: " + v, (Throwable) e); - }).collectList(); - } - pResult = Mono.from(pResult); - } - else { - pResult = Mono.just(result); - } - - return Mono.from(pResult).map(v -> { - if (v instanceof Iterable i) { - List aggregatedResult = (List) StreamSupport.stream(i.spliterator(), false).map(m -> { - return m instanceof Message ? processMessage(responseOkBuilder, (Message) m) : m; - }).collect(Collectors.toList()); - return responseOkBuilder.header("content-type", "application/json").body(aggregatedResult); - } - else if (v instanceof Message) { - return responseOkBuilder.body(processMessage(responseOkBuilder, (Message) v)); - } - else { - return responseOkBuilder.body(v); - } - }); - } - - private static Object processMessage(BodyBuilder responseOkBuilder, Message message) { - responseOkBuilder.headers(HeaderUtils.fromMessage(message.getHeaders())); - return message.getPayload(); - } - - private static FunctionInvocationWrapper doFindFunction(String functionDefinition, HttpMethod method, FunctionCatalog functionCatalog, - Map attributes, String path) { - - path = path.startsWith("/") ? path.substring(1) : path; - if (method.equals(HttpMethod.GET)) { - FunctionInvocationWrapper function = functionCatalog.lookup(path); - if (function != null && function.isSupplier()) { - attributes.put(WebRequestConstants.SUPPLIER, function); - return function; - } - } - - StringBuilder builder = new StringBuilder(); - String name = path; - String value = null; - for (String element : path.split("/")) { - if (builder.length() > 0) { - builder.append("/"); - } - builder.append(element); - name = builder.toString(); - value = path.length() > name.length() ? path.substring(name.length() + 1) - : null; - FunctionInvocationWrapper function = functionCatalog.lookup(name); - if (function != null) { - return postProcessFunction(function, value, attributes); - } - } - - if (StringUtils.hasText(functionDefinition)) { - FunctionInvocationWrapper function = functionCatalog.lookup(functionDefinition); - if (function != null) { - return postProcessFunction(function, value, attributes); - } - } - return null; - } - - private static FunctionInvocationWrapper postProcessFunction(FunctionInvocationWrapper function, String argument, Map attributes) { - attributes.put(WebRequestConstants.FUNCTION, function); - if (argument != null) { - attributes.put(WebRequestConstants.ARGUMENT, argument); - } - return function; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static Object postProcessResult(Object result, boolean isMessage) { - if (result instanceof Flux) { - result = ((Flux) result).map(v -> postProcessResult(v, isMessage)); - } - else if (result instanceof Mono) { - result = ((Mono) result).map(v -> postProcessResult(v, isMessage)); - } - else if (result instanceof Message) { - if (((Message) result).getPayload() instanceof byte[]) { - String str = new String((byte[]) ((Message) result).getPayload()); - result = MessageBuilder.withPayload(str).copyHeaders(((Message) result).getHeaders()).build(); - } - } - - if (result instanceof byte[]) { - result = new String((byte[]) result); - } - return result; - } - -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWrapper.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWrapper.java deleted file mode 100644 index d9b6af26d..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/FunctionWrapper.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2021-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.web.util; - -import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; -import org.springframework.http.HttpHeaders; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * For internal use only. - * - * - * @author Oleg Zhurakousky - * - */ -public class FunctionWrapper { - private final FunctionInvocationWrapper function; - - private final MultiValueMap params = new LinkedMultiValueMap<>(); - - private HttpHeaders headers = new HttpHeaders(); - - private Object argument; - - private final String method; - - /** - * - * @param function instance of {@link FunctionInvocationWrapper} - * @deprecated since 4.0.4 in favor of the constructor that takes Http method as second argument. - */ - @Deprecated - public FunctionWrapper(FunctionInvocationWrapper function) { - this(function, null); - } - - public FunctionWrapper(FunctionInvocationWrapper function, String method) { - this.function = function; - this.method = method; - } - - public HttpHeaders getHeaders() { - return headers; - } - - public void setHeaders(HttpHeaders headers) { - this.headers = headers; - } - - public Object getArgument() { - return argument; - } - - public void setArgument(Object argument) { - this.argument = argument; - } - - public FunctionInvocationWrapper getFunction() { - return function; - } - - public MultiValueMap getParams() { - return params; - } - - public String getMethod() { - return method; - } -} diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/HeaderUtils.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/HeaderUtils.java deleted file mode 100644 index f16c1afb2..000000000 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/util/HeaderUtils.java +++ /dev/null @@ -1,103 +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.web.util; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.http.HttpHeaders; -import org.springframework.messaging.MessageHeaders; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public final class HeaderUtils { - - /** - * Message Header name which contains HTTP request parameters. - */ - public static final String HTTP_REQUEST_PARAM = "http_request_param"; - - private static HttpHeaders IGNORED = new HttpHeaders(); - - private static HttpHeaders REQUEST_ONLY = new HttpHeaders(); - - static { - IGNORED.add(MessageHeaders.ID, ""); - IGNORED.add(HttpHeaders.CONTENT_LENGTH, "0"); - // Headers that would typically be added by a downstream client - REQUEST_ONLY.add(HttpHeaders.ACCEPT, ""); - REQUEST_ONLY.add(HttpHeaders.CONTENT_LENGTH, ""); - REQUEST_ONLY.add(HttpHeaders.CONTENT_TYPE, ""); - REQUEST_ONLY.add(HttpHeaders.HOST, ""); - } - - private HeaderUtils() { - throw new IllegalStateException("Can't instantiate a utility class"); - } - - public static HttpHeaders fromMessage(MessageHeaders headers) { - HttpHeaders result = new HttpHeaders(); - for (String name : headers.keySet()) { - Object value = headers.get(name); - name = name.toLowerCase(); - if (!IGNORED.containsKey(name)) { - Collection values = multi(value); - for (Object object : values) { - result.set(name, object.toString()); - } - } - } - return result; - } - - public static HttpHeaders sanitize(HttpHeaders request) { - HttpHeaders result = new HttpHeaders(); - for (String name : request.keySet()) { - List value = request.get(name); - name = name.toLowerCase(); - if (!IGNORED.containsKey(name) && !REQUEST_ONLY.containsKey(name)) { - result.put(name, value); - } - } - return result; - } - - public static MessageHeaders fromHttp(HttpHeaders headers) { - Map map = new LinkedHashMap<>(); - for (String name : headers.keySet()) { - Collection values = multi(headers.get(name)); - name = name.toLowerCase(); - Object value = values == null ? null - : (values.size() == 1 ? values.iterator().next() : values); - if (name.toLowerCase().equals(HttpHeaders.CONTENT_TYPE.toLowerCase())) { - name = MessageHeaders.CONTENT_TYPE; - } - map.put(name, value); - } - return new MessageHeaders(map); - } - - private static Collection multi(Object value) { - return value instanceof Collection ? (Collection) value : Arrays.asList(value); - } - -} diff --git a/spring-cloud-function-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-function-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json deleted file mode 100644 index 217d1affe..000000000 --- a/spring-cloud-function-web/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "properties": [ - { - "name": "spring.cloud.function.web.path", - "type": "java.lang.String", - "description": "Path to web resources for functions (should start with / if not empty).", - "defaultValue": "" - } - ] -} - diff --git a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories b/spring-cloud-function-web/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 71cbc9fa1..000000000 --- a/spring-cloud-function-web/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,6 +0,0 @@ -org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\ -org.springframework.cloud.function.web.flux.ReactorAutoConfiguration,\ -org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration -org.springframework.context.ApplicationContextInitializer=\ -org.springframework.cloud.function.web.function.FunctionEndpointInitializer,\ -org.springframework.cloud.function.web.source.FunctionExporterInitializer diff --git a/spring-cloud-function-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-function-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 74c853d0b..000000000 --- a/spring-cloud-function-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.cloud.function.web.flux.ReactorAutoConfiguration -org.springframework.cloud.function.web.mvc.ReactorAutoConfiguration -org.springframework.cloud.function.web.source.FunctionExporterAutoConfiguration diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/flux/FluxRestApplicationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/flux/FluxRestApplicationTests.java deleted file mode 100644 index 660910910..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/flux/FluxRestApplicationTests.java +++ /dev/null @@ -1,423 +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.flux; - -import java.net.URI; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.flux.FluxRestApplicationTests.TestConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for vanilla MVC handling (no function layer). Validates the MVC customizations - * that are added in this project independently of the specific concerns of function. - * - * @author Dave Syer - * - */ -// @checkstyle:off -@SpringBootTest(classes = TestConfiguration.class, webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive") -// @checkstyle:on -public class FluxRestApplicationTests { - - private static final MediaType EVENT_STREAM = MediaType.valueOf("text/event-stream"); - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private TestConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - public void wordsSSE() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.get(new URI("/words")).accept(EVENT_STREAM).build(), - String.class).getBody()).isEqualTo(sse("foo", "bar")); - } - - @Test - public void wordsJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/words")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - @Disabled("Fix error handling") - public void errorJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/bang")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void foos() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/foos")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void getMore() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/get/more")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - @Disabled("Should this even work? Or do we need to be explicit about the JSON?") - public void updates() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/updates")).body("one\ntwo"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo("onetwo"); - } - - @Test - public void updatesJson() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo("[\"one\",\"two\"]"); - } - - @Test - public void addFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/addFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void timeout() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/timeout")).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - //@Test - public void emptyJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/empty")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[]"); - } - - @Test - public void sentences() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/sentences")).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptAny() throws Exception { - assertThat( - this.rest - .exchange(RequestEntity.get(new URI("/sentences")) - .accept(MediaType.ALL).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptJson() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.get(new URI("/sentences")) - .accept(MediaType.APPLICATION_JSON).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - assertThat(result.getHeaders().getContentType()) - .isGreaterThanOrEqualTo(MediaType.APPLICATION_JSON); - } - - @Test - public void uppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void uppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void transform() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/transform")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void postMore() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/post/more")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void uppercaseGet() throws Exception { - assertThat(this.rest.exchange(RequestEntity.get(new URI("/uppercase/foo")) - .accept(MediaType.TEXT_PLAIN).build(), String.class).getBody()) - .isEqualTo("[FOO]"); - } - - @Test - public void convertGet() throws Exception { - assertThat(this.rest.exchange(RequestEntity.get(new URI("/wrap/123")) - .accept(MediaType.TEXT_PLAIN).build(), String.class).getBody()) - .isEqualTo("..123.."); - } - - @Test - public void convertGetJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/entity/321")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("{\"value\":321}"); - } - - @Test - public void uppercaseJsonStream() throws Exception { - assertThat( - this.rest.exchange( - RequestEntity.post(new URI("/maps")) - .contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), - String.class).getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void uppercaseSSE() throws Exception { - assertThat(this.rest.exchange(RequestEntity.post(new URI("/uppercase")) - .accept(EVENT_STREAM).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody()) - .isEqualTo(sse("[FOO]", "[BAR]")); - } - - @Test - public void altSSE() throws Exception { - assertThat(this.rest.exchange(RequestEntity.post(new URI("/alt")) - .accept(EVENT_STREAM).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody()) - .isEqualTo(sse("[FOO]", "[BAR]")); - } - - private String sse(String... values) { - return "data:" + StringUtils.arrayToDelimitedString(values, "\n\ndata:") + "\n\n"; - } - - @EnableAutoConfiguration - @RestController - @Configuration - public static class TestConfiguration { - - private List list = new ArrayList<>(); - - @PostMapping({ "/uppercase", "/transform", "/post/more" }) - public Flux uppercase(@RequestBody List flux) { - return Flux.fromIterable(flux).log() - .map(value -> "[" + value.trim().toUpperCase() + "]"); - } - - @PostMapping({ "/alt" }) - public Mono> alt(@RequestBody List flux) { - Publisher result = Flux.fromIterable(flux) - .map(value -> "[" + value.trim().toUpperCase() + "]"); - return Flux.from(result).log() - .then(Mono.fromSupplier(() -> ResponseEntity.ok(result))); - } - - @PostMapping("/upFoos") - public Flux upFoos(@RequestBody List list) { - return Flux.fromIterable(list).log() - .map(value -> new Foo(value.getValue().trim().toUpperCase())); - } - - @GetMapping("/uppercase/{id}") - public Mono> uppercaseGet(@PathVariable String id) { - return Mono.just(id).map(value -> "[" + value.trim().toUpperCase() + "]") - .flatMap(body -> Mono.just(ResponseEntity.ok(body))); - } - - @GetMapping("/wrap/{id}") - public Mono> wrapGet(@PathVariable int id) { - return Mono.just(id).log().map(value -> ".." + value + "..") - .flatMap(body -> Mono.just(ResponseEntity.ok(body))); - } - - @GetMapping("/entity/{id}") - public Mono> entity(@PathVariable Integer id) { - return Mono.just(id).log() - .map(value -> Collections.singletonMap("value", value)); - } - - @PostMapping("/maps") - public Flux> maps( - @RequestBody List> flux) { - return Flux.fromIterable(flux).map(value -> { - value.put("value", value.get("value").trim().toUpperCase()); - return value; - }); - } - - @GetMapping({ "/words", "/get/more" }) - public Flux words() { - return Flux.fromArray(new String[] { "foo", "bar" }); - } - - @GetMapping("/foos") - public Flux foos() { - return Flux.just(new Foo("foo"), new Foo("bar")); - } - - @PostMapping("/updates") - @ResponseStatus(HttpStatus.ACCEPTED) - public Flux updates(@RequestBody List list) { - Flux flux = Flux.fromIterable(list).cache(); - flux.subscribe(value -> this.list.add(value)); - return flux; - } - - @PostMapping("/addFoos") - @ResponseStatus(HttpStatus.ACCEPTED) - public Flux addFoos(@RequestBody List list) { - Flux flux = Flux.fromIterable(list).cache(); - flux.subscribe(value -> this.list.add(value.getValue())); - return flux; - } - - @GetMapping("/bang") - public Flux bang() { - return Flux.fromArray(new String[] { "foo", "bar" }).map(value -> { - if (value.equals("bar")) { - throw new RuntimeException("Bar"); - } - return value; - }); - } - - @GetMapping("/empty") - public Flux empty() { - return Flux.fromIterable(Collections.emptyList()); - } - - @GetMapping("/timeout") - public Flux timeout() { - return Flux.defer(() -> Flux.create(emitter -> { - emitter.next("foo"); - }).timeout(Duration.ofMillis(100L), Flux.empty())); - } - - @GetMapping("/sentences") - public Flux> sentences() { - return Flux.just(Arrays.asList("go", "home"), Arrays.asList("come", "back")); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/mvc/MvcRestApplicationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/mvc/MvcRestApplicationTests.java deleted file mode 100644 index 1d051ae3b..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/mvc/MvcRestApplicationTests.java +++ /dev/null @@ -1,402 +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.mvc; - -import java.net.URI; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.mvc.MvcRestApplicationTests.TestConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for vanilla MVC handling (no function layer). Validates the MVC customizations - * that are added in this project independently of the specific concerns of function. - * - * @author Dave Syer - * - */ -// @checkstyle:off -@SpringBootTest(classes = TestConfiguration.class, webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=servlet") -// @checkstyle:on -public class MvcRestApplicationTests { - - private static final MediaType EVENT_STREAM = MediaType.valueOf("text/event-stream"); - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private TestConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - public void wordsSSE() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.get(new URI("/words")).accept(EVENT_STREAM).build(), - String.class).getBody()).isEqualTo(sse("foo", "bar")); - } - - @Test - public void wordsJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/words")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - @Disabled("Fix error handling") - public void errorJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/bang")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void foos() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/foos")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void getMore() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/get/more")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - @Disabled("Should this even work? Or do we need to be explicit about the JSON?") - public void updates() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/updates")).body("one\ntwo"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo("onetwo"); - } - - @Test - public void updatesJson() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo("[\"one\",\"two\"]"); - } - - @Test - public void addFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/addFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void timeout() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/timeout")).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void emptyJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/empty")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[]"); - } - - @Test - public void sentences() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/sentences")).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptAny() throws Exception { - assertThat( - this.rest - .exchange(RequestEntity.get(new URI("/sentences")) - .accept(MediaType.ALL).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptJson() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.get(new URI("/sentences")) - .accept(MediaType.APPLICATION_JSON).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - assertThat(result.getHeaders().getContentType()) - .isGreaterThanOrEqualTo(MediaType.APPLICATION_JSON); - } - - @Test - public void uppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void uppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void transform() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/transform")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void postMore() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/post/more")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"[FOO]\",\"[BAR]\"]"); - } - - @Test - public void uppercaseGet() { - assertThat(this.rest.getForObject("/uppercase/foo", String.class)) - .isEqualTo("[FOO]"); - } - - @Test - public void convertGet() { - assertThat(this.rest.getForObject("/wrap/123", String.class)) - .isEqualTo("..123.."); - } - - @Test - public void convertGetJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/entity/321")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("{\"value\":321}"); - } - - @Test - public void uppercaseJsonStream() throws Exception { - assertThat( - this.rest.exchange( - RequestEntity.post(new URI("/maps")) - .contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), - String.class).getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void uppercaseSSE() throws Exception { - assertThat(this.rest.exchange(RequestEntity.post(new URI("/uppercase")) - .accept(EVENT_STREAM).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody()) - .isEqualTo(sse("[FOO]", "[BAR]")); - } - - private String sse(String... values) { - return "data:" + StringUtils.arrayToDelimitedString(values, "\n\ndata:") + "\n\n"; - } - - @EnableAutoConfiguration - @RestController - @Configuration - public static class TestConfiguration { - - private List list = new ArrayList<>(); - - @PostMapping({ "/uppercase", "/transform", "/post/more" }) - public Flux uppercase(@RequestBody List flux) { - return Flux.fromIterable(flux).log() - .map(value -> "[" + value.trim().toUpperCase() + "]"); - } - - @PostMapping("/upFoos") - public Flux upFoos(@RequestBody List list) { - return Flux.fromIterable(list).log() - .map(value -> new Foo(value.getValue().trim().toUpperCase())); - } - - @GetMapping("/uppercase/{id}") - public Mono uppercaseGet(@PathVariable String id) { - return Mono.just(id).map(value -> "[" + value.trim().toUpperCase() + "]"); - } - - @GetMapping("/wrap/{id}") - public Mono wrapGet(@PathVariable int id) { - return Mono.just(id).log().map(value -> ".." + value + ".."); - } - - @GetMapping("/entity/{id}") - public Mono> entity(@PathVariable Integer id) { - return Mono.just(id).log() - .map(value -> Collections.singletonMap("value", value)); - } - - @PostMapping("/maps") - public Flux> maps( - @RequestBody List> flux) { - return Flux.fromIterable(flux).map(value -> { - value.put("value", value.get("value").trim().toUpperCase()); - return value; - }); - } - - @GetMapping({ "/words", "/get/more" }) - public Flux words() { - return Flux.fromArray(new String[] { "foo", "bar" }); - } - - @GetMapping("/foos") - public Flux foos() { - return Flux.just(new Foo("foo"), new Foo("bar")); - } - - @PostMapping("/updates") - @ResponseStatus(HttpStatus.ACCEPTED) - public Flux updates(@RequestBody List list) { - Flux flux = Flux.fromIterable(list).cache(); - flux.subscribe(value -> this.list.add(value)); - return flux; - } - - @PostMapping("/addFoos") - @ResponseStatus(HttpStatus.ACCEPTED) - public Flux addFoos(@RequestBody List list) { - Flux flux = Flux.fromIterable(list).cache(); - flux.subscribe(value -> this.list.add(value.getValue())); - return flux; - } - - @GetMapping("/bang") - public Flux bang() { - return Flux.fromArray(new String[] { "foo", "bar" }).map(value -> { - if (value.equals("bar")) { - throw new RuntimeException("Bar"); - } - return value; - }); - } - - @GetMapping("/empty") - public Flux empty() { - return Flux.fromIterable(Collections.emptyList()); - } - - @GetMapping("/timeout") - public Flux timeout() { - return Flux.defer(() -> Flux.create(emitter -> { - emitter.next("foo"); - }).timeout(Duration.ofMillis(100L), Flux.empty())); - } - - @GetMapping("/sentences") - public Flux> sentences() { - return Flux.just(Arrays.asList("go", "home"), Arrays.asList("come", "back")); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/scan/ComponentTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/scan/ComponentTests.java deleted file mode 100644 index 9c9cfc64f..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/scan/ComponentTests.java +++ /dev/null @@ -1,88 +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.scan; - -import java.net.URI; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class ComponentTests { - - @LocalServerPort - private int port; - - @Autowired - private Greeter greeter; - - @Autowired - private TestRestTemplate rest; - - @Test - public void contextLoads() throws Exception { - assertThat(this.greeter).isNotNull(); - } - - @Test - public void greeter() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/greeter")) - .contentType(MediaType.TEXT_PLAIN).body("World"), - String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"Hello World\"]"); - } - - @SpringBootApplication - @ComponentScan - protected static class TestConfiguration { - - } - - @Component("greeter") - protected static class Greeter implements Function, Flux> { - - @Override - public Flux apply(Flux flux) { - return flux.map(name -> "Hello " + name); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ExplicitNonFunctionalTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ExplicitNonFunctionalTests.java deleted file mode 100644 index a25046754..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ExplicitNonFunctionalTests.java +++ /dev/null @@ -1,62 +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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Dave Syer - * - */ -@SpringBootTest({ "spring.main.web-application-type=REACTIVE", - "spring.functional.enabled=false" }) -@AutoConfigureWebTestClient -@DirtiesContext -public class ExplicitNonFunctionalTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() throws Exception { - this.client.post().uri("/").body(Mono.just("foo"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("FOO"); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - protected static class TestConfiguration implements Function { - - @Override - public String apply(String value) { - return value.toUpperCase(); - } - - } - -} 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 deleted file mode 100644 index 0f0826e83..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalExporterTests.java +++ /dev/null @@ -1,147 +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.test; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -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.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.cloud.function.test.FunctionalExporterTests.ApplicationConfiguration; -import org.springframework.cloud.function.web.TestSocketUtils; -import org.springframework.cloud.function.web.source.SupplierExporter; -import org.springframework.context.ApplicationContextInitializer; -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 static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -@FunctionalSpringBootTest(classes = ApplicationConfiguration.class, webEnvironment = WebEnvironment.NONE, properties = { - "spring.main.web-application-type=none", - "spring.cloud.function.web.export.sink.url=http://localhost:${my.port}", - "spring.cloud.function.web.export.source.url=http://localhost:${my.port}", - "spring.cloud.function.web.export.sink.name=origin|uppercase", - "spring.cloud.function.web.export.sink.contentType=text/plain", - "spring.cloud.function.web.export.debug=true" }) -@Disabled -public class FunctionalExporterTests { - - @Autowired - private SupplierExporter forwarder; - - private static RestPojoConfiguration app; - - private static ConfigurableApplicationContext context; - - private static Map headers = new HashMap<>(); - - @BeforeAll - public static void init() throws Exception { - headers.clear(); - String port = "" + TestSocketUtils.findAvailableTcpPort(); - System.setProperty("server.port", port); - System.setProperty("my.port", port); - context = SpringApplication.run(RestPojoConfiguration.class, - "--spring.main.web-application-type=reactive"); - app = context.getBean(RestPojoConfiguration.class); - // Sometimes the server doesn't start quick enough - Thread.sleep(500L); - } - - @AfterAll - public static void close() { - headers.clear(); - System.clearProperty("server.port"); - if (context != null) { - context.close(); - } - } - - @Test - public void words() throws Exception { - int count = 0; - while (this.forwarder.isRunning() && count++ < 10) { - Thread.sleep(50); - } - // It completed - assertThat(FunctionalExporterTests.app.inputs).contains("HELLO"); - assertThat(this.forwarder.isOk()).isTrue(); - assertThat(headers.containsKey("scf-sink-url")); - assertThat(headers.containsKey("scf-func-name")); - } - - @SpringBootConfiguration - protected static class ApplicationConfiguration - implements ApplicationContextInitializer { - - Function, Message> uppercase() { - return value -> { - headers.putAll(value.getHeaders()); - return MessageBuilder.withPayload(value.getPayload().getName().toUpperCase()) - .copyHeaders(value.getHeaders()).build(); - }; - } - - @Override - public void initialize(GenericApplicationContext context) { - context.registerBean("uppercase", FunctionRegistration.class, - () -> 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(); - } - } - -} - -class Person { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalTests.java deleted file mode 100644 index 00883f4c8..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalTests.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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Dave Syer - * - */ -// Only need web-application-type because MVC is on the classpath -@FunctionalSpringBootTest("spring.main.web-application-type=reactive") -@AutoConfigureWebTestClient -public class FunctionalTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() throws Exception { - this.client.post().uri("/").body(Mono.just("foo"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("FOO"); - } - - @SpringBootConfiguration - protected static class TestConfiguration implements Function { - - @Override - public String apply(String value) { - return value.toUpperCase(); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputListTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputListTests.java deleted file mode 100644 index d30b7df71..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputListTests.java +++ /dev/null @@ -1,89 +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.test; - -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Dave Syer - * - */ -@FunctionalSpringBootTest("spring.main.web-application-type=reactive") -@AutoConfigureWebTestClient -public class FunctionalWithInputListTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() throws Exception { - this.client.post().uri("/") - .body(Mono.just("[{\"value\":\"foo\"}, {\"value\":\"bar\"}]"), - String.class) - .exchange().expectStatus().isOk().expectBody(String.class) - .isEqualTo("{\"value\":\"FOOBAR\"}"); - } - - @SpringBootConfiguration - protected static class TestConfiguration implements Function, Foo> { - - @Override - public Foo apply(List value) { - return new Foo(value.stream().map(foo -> foo.getValue().toUpperCase()) - .collect(Collectors.joining())); - } - - } - - public 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; - } - - @Override - public String toString() { - return "Foo [value=" + this.value + "]"; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputSetTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputSetTests.java deleted file mode 100644 index 066959957..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/FunctionalWithInputSetTests.java +++ /dev/null @@ -1,97 +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.test; - -import java.time.Duration; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.test.web.reactive.server.WebTestClient; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@FunctionalSpringBootTest("spring.main.web-application-type=reactive") -@AutoConfigureWebTestClient -public class FunctionalWithInputSetTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() throws Exception { - this.client = this.client.mutate().responseTimeout(Duration.ofSeconds(300)).build(); - String reply = this.client - .post().uri("/") - .body(Mono.just("[{\"value\":\"foo\"}, {\"value\":\"bar\"}]"), String.class) - .exchange() - .expectStatus().isOk().expectBody(String.class).returnResult() - .getResponseBody(); - assertThat(reply.contains("FOO")).isTrue(); - assertThat(reply.contains("BAR")).isTrue(); - assertThat(reply.contains("{\"value\":\"")).isTrue(); - } - - @SpringBootConfiguration - protected static class TestConfiguration implements Function, Foo> { - - @Override - public Foo apply(Set value) { - return new Foo(value.stream().map(foo -> foo.getValue().toUpperCase()) - .collect(Collectors.joining())); - } - - } - - public 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; - } - - @Override - public String toString() { - return "Foo [value=" + this.value + "]"; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/HeadersToMessageTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/HeadersToMessageTests.java deleted file mode 100644 index 710843883..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/HeadersToMessageTests.java +++ /dev/null @@ -1,68 +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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.web.reactive.server.WebTestClient; - - -/** - * @author Oleg Zhurakousky - * - */ -// Only need web-application-type because MVC is on the classpath -@FunctionalSpringBootTest("spring.main.web-application-type=reactive") -@AutoConfigureWebTestClient -public class HeadersToMessageTests { - - @Autowired - private WebTestClient client; - - @Test - public void testBodyAndCustomHeaderFromMessagePropagation() throws Exception { - this.client.post().uri("/").body(Mono.just("foo"), String.class).exchange() - .expectStatus().isOk().expectHeader() - .valueEquals("x-content-type", "application/xml").expectHeader() - .valueEquals("foo", "bar").expectBody(String.class).isEqualTo("FOO"); - } - - @SpringBootConfiguration - protected static class TestConfiguration - implements Function, Message> { - - @Override - public Message apply(Message request) { - Message message = MessageBuilder - .withPayload(request.getPayload().toUpperCase()) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build(); - return message; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ImplicitNonFunctionalTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ImplicitNonFunctionalTests.java deleted file mode 100644 index 28e067430..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/ImplicitNonFunctionalTests.java +++ /dev/null @@ -1,62 +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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Dave Syer - * - */ -@SpringBootTest("spring.main.web-application-type=REACTIVE") -@AutoConfigureWebTestClient -@DirtiesContext -public class ImplicitNonFunctionalTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() throws Exception { - this.client.post().uri("/").body(Mono.just("foo"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("FOO"); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - protected static class TestConfiguration { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/MoreThenOneFunctionRootMappingTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/MoreThenOneFunctionRootMappingTests.java deleted file mode 100644 index 1482024c5..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/MoreThenOneFunctionRootMappingTests.java +++ /dev/null @@ -1,69 +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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Oleg Zhurakousky - * - */ -@SpringBootTest({ "spring.main.web-application-type=REACTIVE", - "spring.functional.enabled=false", - "spring.cloud.function.definition=uppercase|reverse" }) -@AutoConfigureWebTestClient -@DirtiesContext -public class MoreThenOneFunctionRootMappingTests { - - @Autowired - private WebTestClient client; - - @Test - public void words() { - this.client.post().uri("/").body(Mono.just("star"), String.class).exchange() - .expectStatus().isOk().expectBody(String.class).isEqualTo("RATS"); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - protected static class TestConfiguration { - - @Bean - public Function uppercase() { - return String::toUpperCase; - } - - @Bean - public Function reverse() { - return v -> new StringBuilder(v).reverse().toString(); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/PojoTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/PojoTests.java deleted file mode 100644 index b622e8a0f..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/PojoTests.java +++ /dev/null @@ -1,94 +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.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.cloud.function.context.test.FunctionalSpringBootTest; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Dave Syer - * - */ -// Only need web-application-type because MVC is on the classpath -@FunctionalSpringBootTest("spring.main.web-application-type=reactive") -@AutoConfigureWebTestClient -public class PojoTests { - - @Autowired - private WebTestClient client; - - @Test - public void single() throws Exception { - this.client.post().uri("/").body(Mono.just("{\"value\":\"foo\"}"), String.class) - .exchange().expectStatus().isOk().expectBody(String.class) - .isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void multiple() throws Exception { - this.client.post().uri("/") - .body(Mono.just("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), - String.class) - .exchange().expectStatus().isOk().expectBody(String.class) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @SpringBootConfiguration - protected static class TestConfiguration implements Function { - - @Override - public Foo apply(Foo value) { - return new Foo(value.getValue().toUpperCase()); - } - - } - -} - -class Foo { - - private String value; - - Foo() { - } - - Foo(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - @Override - public String toString() { - return "Foo [value=" + this.value + "]"; - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestConfiguration.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestConfiguration.java deleted file mode 100644 index 39bb8fae7..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestConfiguration.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018-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.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -@SpringBootConfiguration -@EnableAutoConfiguration -@RestController -public class RestConfiguration { - - private static Log logger = LogFactory.getLog(RestConfiguration.class); - - List inputs = new ArrayList<>(); - - private Iterator outputs = Arrays.asList("hello", "world").iterator(); - - @GetMapping("/") - ResponseEntity home() { - logger.info("HOME"); - if (this.outputs.hasNext()) { - return ResponseEntity.ok(this.outputs.next()); - } - return ResponseEntity.notFound().build(); - } - - @PostMapping("/") - ResponseEntity accept(@RequestBody String body) { - logger.info("ACCEPT"); - this.inputs.add(body); - return ResponseEntity.accepted().body(body); - } - - public static void main(String[] args) throws Exception { - SpringApplication.run(RestConfiguration.class, args); - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestPojoConfiguration.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestPojoConfiguration.java deleted file mode 100644 index fbb89d14f..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/test/RestPojoConfiguration.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018-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.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -@SpringBootConfiguration -@EnableAutoConfiguration -@RestController -public class RestPojoConfiguration { - - private static Log logger = LogFactory.getLog(RestPojoConfiguration.class); - - List inputs = new ArrayList<>(); - - private Iterator outputs = Arrays.asList("{\"name\":\"hello\"}").iterator(); - - @GetMapping("/") - ResponseEntity home() { - logger.info("HOME"); - if (this.outputs.hasNext()) { - return ResponseEntity.ok(this.outputs.next()); - } - return ResponseEntity.notFound().build(); - } - - @PostMapping("/") - ResponseEntity accept(@RequestBody String body) { - logger.info("ACCEPT"); - this.inputs.add(body); - return ResponseEntity.accepted().body(body); - } - - public static void main(String[] args) throws Exception { - SpringApplication.run(RestPojoConfiguration.class, args); - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/TestSocketUtils.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/TestSocketUtils.java deleted file mode 100644 index 5c35613de..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/TestSocketUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2022-2022 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.net.InetAddress; -import java.net.ServerSocket; -import java.util.Random; - -import javax.net.ServerSocketFactory; - -/** - * Simple test utility to find a random available TCP port. - *

Inspired by the now removed {@code org.springframework.util.SocketUtils} and is only used in a testing capacity. - * - * @author Chris Bono - * @deprecated will soon be removed or consolidated - do not use further - */ -@Deprecated -public final class TestSocketUtils { - - private static final Random random = new Random(System.nanoTime()); - - private TestSocketUtils() { - } - - /** - * Find an available TCP port randomly selected from the range {@code 1024-65535}. - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort() { - int minPort = 1024; - int maxPort = 65535; - int portRange = maxPort - minPort; - int candidatePort; - int searchCounter = 0; - do { - if (searchCounter > portRange) { - throw new IllegalStateException(String.format( - "Could not find an available TCP port after %d attempts", searchCounter)); - } - candidatePort = minPort + random.nextInt(portRange + 1); - searchCounter++; - } - while (!isPortAvailable(candidatePort)); - - return candidatePort; - } - - private static boolean isPortAvailable(int port) { - try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( - port, 1, InetAddress.getByName("localhost")); - serverSocket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HeadersToMessageTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HeadersToMessageTests.java deleted file mode 100644 index 06ec2bdb1..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HeadersToMessageTests.java +++ /dev/null @@ -1,130 +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.web.flux; - -import java.net.URI; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * @author Adrien Poupard - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.cloud.function.web.path=/functions", - "spring.main.web-application-type=reactive" }) -@ContextConfiguration(classes = { RestApplication.class, HeadersToMessageTests.TestConfiguration.class }) -public class HeadersToMessageTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void testBodyAndCustomHeaderFromMessagePropagation() throws Exception { - // test POJO paylod - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/employee")) - .contentType(MediaType.APPLICATION_JSON) - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("{\"name\":\"Bob\",\"age\":25}"); - assertThat(postForEntity.getHeaders().containsKey("x-content-type")).isTrue(); - assertThat(postForEntity.getHeaders().get("x-content-type").get(0)) - .isEqualTo("application/xml"); - assertThat(postForEntity.getHeaders().get("foo").get(0)).isEqualTo("bar"); - - // test simple type payload - postForEntity = this.rest.postForEntity(new URI("/functions/string"), - "{\"name\":\"Bob\",\"age\":25}", String.class); - assertThat(postForEntity.getBody()).isEqualTo("{\"name\":\"Bob\",\"age\":25}"); - assertThat(postForEntity.getHeaders().containsKey("x-content-type")).isTrue(); - assertThat(postForEntity.getHeaders().get("x-content-type").get(0)) - .isEqualTo("application/xml"); - assertThat(postForEntity.getHeaders().get("foo").get(0)).isEqualTo("bar"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean({ "string" }) - public Function, Message> functiono() { - return request -> { - Message message = MessageBuilder.withPayload(request.getPayload()) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build(); - return message; - }; - } - - @Bean({ "employee" }) - public Function, Message> function1() { - return request -> { - Message message = MessageBuilder - .withPayload(request.getPayload()) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build(); - return message; - }; - } - - } - - @SuppressWarnings("unused") // used by json converter - private static class Employee { - - private String name; - - private int age; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return this.age; - } - - public void setAge(int age) { - this.age = age; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpGetIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpGetIntegrationTests.java deleted file mode 100644 index 2505c6a53..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpGetIntegrationTests.java +++ /dev/null @@ -1,383 +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.web.flux; - -import java.net.URI; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -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.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.flux.HttpGetIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"spring.main.web-application-type=reactive", "debug=true"}) -@ContextConfiguration(classes = { RestApplication.class, ApplicationConfiguration.class }) -@DirtiesContext -public class HttpGetIntegrationTests { - - private static final MediaType EVENT_STREAM = MediaType.TEXT_EVENT_STREAM; - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private ApplicationConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - public void staticResource() { - assertThat(this.rest.getForObject("/test.html", String.class)) - .contains("Test"); - } - - @Test - public void wordsSSE() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.get(new URI("/words")).accept(EVENT_STREAM).build(), - String.class).getBody()).isEqualTo(sse("foo", "bar")); - } - - @Test - public void wordsJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/words")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void errorJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/bang")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void word() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/word")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("foo"); - } - - @Test - public void foos() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/foos")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void getMore() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/get/more")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void bareWords() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/bareWords")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void timeoutJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/timeout")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void emptyJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/empty")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[]"); - } - - @Test - public void sentences() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/sentences")).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptAny() throws Exception { - assertThat( - this.rest - .exchange(RequestEntity.get(new URI("/sentences")) - .accept(MediaType.ALL).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptJson() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.get(new URI("/sentences")) - .accept(MediaType.APPLICATION_JSON).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - assertThat(result.getHeaders().getContentType()) - .isGreaterThanOrEqualTo(MediaType.APPLICATION_JSON); - } - - @Test - public void sentencesAcceptSse() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/sentences")).accept(EVENT_STREAM).build(), - String.class); - assertThat(result.getBody()) - .isEqualTo(sse("[\"go\",\"home\"]", "[\"come\",\"back\"]")); - assertThat(result.getHeaders().getContentType().isCompatibleWith(EVENT_STREAM)) - .isTrue(); - } - - @Test - public void postMoreFoo() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .get(new URI("/post/more/foo")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\"]"); - } - - @Test - public void uppercaseGet() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .get(new URI("/uppercase/foo")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\"]"); - } - - @Test - public void convertGet() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .get(new URI("/wrap/123")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[\"..123..\"]"); - } - - @Test - public void supplierFirst() { - assertThat(this.rest.getForObject("/not/a/function", String.class)) - .isEqualTo("[\"hello\"]"); - } - - @Test - public void convertGetJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/entity/321")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[{\"value\":321}]"); - } - - @Test - public void compose() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .get(new URI("/concat,reverse/foo")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[\"oofoof\"]"); - } - - private String sse(String... values) { - return "data:" + StringUtils.arrayToDelimitedString(values, "\n\ndata:") + "\n\n"; - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - private List list = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - SpringApplication.run(HttpGetIntegrationTests.ApplicationConfiguration.class, - args); - } - - @Bean - public Function, Flux> concat() { - return flux -> flux.map(v -> v + v); - } - - @Bean - public Function, Flux> reverse() { - return flux -> flux.log() - .map(value -> new StringBuilder(value.trim()).reverse().toString()); - } - - @Bean({ "uppercase", "post/more" }) - public Function, Flux> uppercase() { - return flux -> flux.log() - .map(value -> "(" + value.trim().toUpperCase() + ")"); - } - - @Bean - public Function, Flux> wrap() { - return flux -> flux.log().map(value -> ".." + value + ".."); - } - - @Bean - public Function, Flux>> entity() { - return flux -> flux.log() - .map(value -> Collections.singletonMap("value", value)); - } - - @Bean({ "words", "get/more" }) - public Supplier> words() { - return () -> Flux.just("foo", "bar"); - } - - @Bean - public Supplier word() { - return () -> "foo"; - } - - @Bean - public Supplier> foos() { - return () -> Flux.just(new Foo("foo"), new Foo("bar")); - } - - @Bean - public Supplier> bareWords() { - return () -> Arrays.asList("foo", "bar"); - } - - @Bean - public Supplier> bang() { - return () -> Flux.fromArray(new String[] { "foo", "bar" }).map(value -> { - if (value.equals("bar")) { - throw new RuntimeException("Bar"); - } - return value; - }); - } - - @Bean - public Supplier> empty() { - return () -> Flux.fromIterable(Collections.emptyList()); - } - - @Bean("not/a/function") - public Supplier> supplier() { - return () -> Flux.just("hello"); - } - - @Bean("not/a") - public Function, Flux> function() { - return input -> Flux.just("bye"); - } - - @Bean - public Supplier> timeout() { - return () -> Flux.defer(() -> Flux.create(emitter -> { - emitter.next("foo"); - }).timeout(Duration.ofMillis(100L), Flux.empty())); - } - - @Bean - public Supplier>> sentences() { - return () -> Flux.just(Arrays.asList("go", "home"), - Arrays.asList("come", "back")); - } - - @Bean - public Function, Map> sum() { - return valueMap -> valueMap.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, values -> values - .getValue().stream().mapToInt(Integer::parseInt).sum())); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpPostIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpPostIntegrationTests.java deleted file mode 100644 index 0598c06f7..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/HttpPostIntegrationTests.java +++ /dev/null @@ -1,553 +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.web.flux; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.flux.HttpPostIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.util.Assert; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive") -@ContextConfiguration(classes = { RestApplication.class, ApplicationConfiguration.class }) -public class HttpPostIntegrationTests { - - private static final MediaType EVENT_STREAM = MediaType.TEXT_EVENT_STREAM; - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private ApplicationConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @AfterEach - public void done() { - this.test.list.clear(); - } - - @Test - @DirtiesContext - public void qualifierFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/foos")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"[FOO]\"},{\"value\":\"[BAR]\"}]"); - } - - @Test - @DirtiesContext - public void updates() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\", \"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isNull(); - } - - @Test - @DirtiesContext - public void updatesJson() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo(null); - } - - @Test - @DirtiesContext - public void addFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/addFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo(null); - } - - @Test - @DirtiesContext - public void addFoosFlux() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/addFoosFlux")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo(null); - } - - @Test - @DirtiesContext - public void bareUpdates() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpdates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - } - - @Test - @DirtiesContext - public void uppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void messages() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/messages")).contentType(MediaType.APPLICATION_JSON) - .header("x-foo", "bar").body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getHeaders().getFirst("x-foo")).isEqualTo("bar"); - assertThat(result.getHeaders()).doesNotContainKey("id"); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void headers() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/headers")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); -// assertThat(result.getHeaders().getFirst("foo")).isEqualTo("bar"); -// assertThat(result.getHeaders()).doesNotContainKey("id"); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void uppercaseSingleValue() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/uppercase")) - .contentType(MediaType.TEXT_PLAIN).body("foo"), - String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\"]"); - } - - @Test - @Disabled("WebFlux would split the request body into lines: TODO make this work the same") - public void uppercasePlainText() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/uppercase")) - .contentType(MediaType.TEXT_PLAIN).body("foo\nbar"), - String.class); - assertThat(result.getBody()).isEqualTo("(FOO\nBAR)"); - } - - @Test - @DirtiesContext - public void uppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - @DirtiesContext - public void uppercaseFoo() throws Exception { - // Single Foo can be parsed - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()).isEqualTo("[{\"value\":\"FOO\"}]"); - } - - @Test - @DirtiesContext - public void bareUppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - @DirtiesContext - @Disabled // not sure if this test is correct. Why does ? has to be assumed as String? - public void typelessFunctionPassingArray() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/typelessFunctionExpectingText")) - .contentType(MediaType.TEXT_PLAIN).body("[{\"value\":\"foo\"}]"), - String.class); - assertThat(result.getBody()).isEqualTo("[{\"value\":\"foo\"}]"); - } - - @Test - @DirtiesContext - public void bareUppercaseFoo() throws Exception { - // Single Foo can be parsed and returns a single value if the function is defined - // that way - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) - .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - @DirtiesContext - public void bareUppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void singleValuedText() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/bareUppercase")).accept(MediaType.TEXT_PLAIN) - .contentType(MediaType.TEXT_PLAIN).body("foo"), - String.class); - assertThat(result.getBody()).isEqualTo("(FOO)"); - } - - @Test - @DirtiesContext - public void transform() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/transform")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void postMore() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/post/more")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - @DirtiesContext - public void convertPost() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/wrap")) - .contentType(MediaType.TEXT_PLAIN).body("123"), - String.class); - // Result is multi-valued so it has to come out as an array - assertThat(result.getBody()).isEqualTo("[\"..123..\"]"); - } - - @Test - @DirtiesContext - public void convertPostJson() throws Exception { - // If you POST a single value to a Function,Flux> it can't - // determine if the output is single valued, so it has to send an array back - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/doubler")) - .contentType(MediaType.TEXT_PLAIN).body("123"), - String.class); - assertThat(result.getBody()).isEqualTo("[246]"); - } - - @Test - @DirtiesContext - public void uppercaseJsonArray() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/maps")) - .contentType(MediaType.APPLICATION_JSON) - // The new line in the middle is optional - .body("[{\"value\":\"foo\"},\n{\"value\":\"bar\"}]"), - String.class).getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - @DirtiesContext - public void uppercaseSSE() throws Exception { - String s = this.rest.exchange(RequestEntity.post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody(); - assertThat(this.rest.exchange(RequestEntity.post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody()) - .isEqualTo(sse("(FOO)", "(BAR)")); - } - - @Test - @DirtiesContext - public void sum() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/sum")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - - @Test - @DirtiesContext - @Disabled - public void multipart() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/sum")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.MULTIPART_FORM_DATA).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - - @Test - @DirtiesContext - @Disabled - public void count() throws Exception { - List list = Arrays.asList("A", "B", "A"); - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/count")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON).body(list), - String.class).getBody()).isEqualTo("{\"A\":2,\"B\":1}"); - } - - @Test - @DirtiesContext - @Disabled - public void fluxWithList() throws Exception { - List list = Arrays.asList("A", "B", "A"); - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/fluxCollectionEcho")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON).body(list), - String.class).getBody()).isEqualTo("[\"A\",\"B\",\"A\"]"); - } - - private String sse(String... values) { - return "[\"" + StringUtils.arrayToDelimitedString(values, "\",\"") + "\"]"; - } - - @EnableAutoConfiguration - public static class ApplicationConfiguration { - - private List list = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - SpringApplication.run(HttpPostIntegrationTests.ApplicationConfiguration.class, - args); - } - - @Bean({ "uppercase", "transform", "post/more" }) - public Function, Flux> uppercase() { - return flux -> flux.log() - .map(value -> "(" + value.trim().toUpperCase() + ")"); - } - - @Bean - public Function bareUppercase() { - return value -> "(" + value.trim().toUpperCase() + ")"; - } - - @Bean - public Function, Message> messages() { - return value -> MessageBuilder - .withPayload("(" + value.getPayload().trim().toUpperCase() + ")") - .copyHeaders(value.getHeaders()).build(); - } - - @Bean - public Function>, Flux>> headers() { - return flux -> flux.map(value -> MessageBuilder - .withPayload("(" + value.getPayload().trim().toUpperCase() + ")") - .setHeader("foo", "bar").build()); - } - - @Bean - public Function, Flux> upFoos() { - return flux -> flux.log() - .map(value -> new Foo(value.getValue().trim().toUpperCase())); - } - - @Bean - public Function bareUpFoos() { - return value -> new Foo(value.getValue().trim().toUpperCase()); - } - - @Bean - public Function typelessFunctionExpectingText() { - return value -> { - Assert.isInstanceOf(String.class, value); - return value; - }; - } - - @Bean - public Function, Flux> wrap() { - return flux -> flux.log().map(value -> ".." + value + ".."); - } - - @Bean - public Function, Flux> doubler() { - return flux -> flux.log().map(value -> 2 * value); - } - - @Bean - public Function>, Flux>> maps() { - return flux -> flux.map(value -> { - value.put("value", value.get("value").trim().toUpperCase()); - return value; - }); - } - - @Bean - @Qualifier("foos") - public Function qualifier() { - return value -> { - return new Foo("[" + value.trim().toUpperCase() + "]"); - }; - } - - @Bean - public Consumer> updates() { - return flux -> flux.subscribe(value -> { - System.out.println(); - this.list.add(value); - }); - } - - @Bean - public Consumer> addFoosFlux() { - return flux -> flux.subscribe(value -> this.list.add(value.getValue())); - } - - @Bean - public Consumer addFoos() { - return value -> { - this.list.add(value.getValue()); - }; - } - - @Bean - public Consumer bareUpdates() { - return value -> { - this.list.add(value); - }; - } - - @Bean("not/a") - public Function, Flux> function() { - return input -> Flux.just("bye"); - } - - @Bean - public Function, Map> sum() { - return valueMap -> valueMap.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, values -> values - .getValue().stream().mapToInt(Integer::parseInt).sum())); - } - - @Bean - public Function, Mono>> count() { - return flux -> flux.collect(HashMap::new, - (map, word) -> map.merge(word, 1, Integer::sum)); - } - - @Bean - public Function>, Flux> fluxCollectionEcho() { - return flux -> flux.flatMap(v -> Flux.fromIterable(v)); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/PrefixTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/PrefixTests.java deleted file mode 100644 index fcadd4683..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/PrefixTests.java +++ /dev/null @@ -1,83 +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.web.flux; - -import java.net.URI; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.flux.PrefixTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.main.web-application-type=reactive", - "spring.cloud.function.web.path=/functions", "debug" }) -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class PrefixTests { - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/functions/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void missing() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean({ "words", "get/more" }) - public Supplier> words() { - return () -> Flux.fromArray(new String[] { "foo", "bar" }); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/SingletonTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/SingletonTests.java deleted file mode 100644 index c2c85f328..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/flux/SingletonTests.java +++ /dev/null @@ -1,104 +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.web.flux; - -import java.net.URI; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.flux.SingletonTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive") -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class SingletonTests { - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean - public static BeanDefinitionRegistryPostProcessor processor() { - return new BeanDefinitionRegistryPostProcessor() { - - @Override - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) - throws BeansException { - } - - @Override - public void postProcessBeanDefinitionRegistry( - BeanDefinitionRegistry registry) throws BeansException { - // Simulates what happens when you add a compiled function - RootBeanDefinition beanDefinition = new RootBeanDefinition( - MySupplier.class); - registry.registerBeanDefinition("words", beanDefinition); - } - }; - } - - } - - public static class MySupplier implements Supplier> { - - @Override - public Flux get() { - return Flux.just("foo", "bar"); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerMVCTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerMVCTests.java deleted file mode 100644 index e6aa8efd4..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerMVCTests.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2019-2022 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.function; - -import java.net.URI; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 2.1 - */ -public class FunctionEndpointInitializerMVCTests { - - @Test - public void testSingleFunctionMapping() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(ApplicationConfiguration.class, "--server.port=0"); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - String port = context.getEnvironment().getProperty("local.server.port"); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/uppercase"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("STRESSED"); - response = testRestTemplate.postForEntity(new URI("http://localhost:" + port + "/reverse"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("desserts"); - } - - @Test - public void testCompositionFunctionMapping() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(ApplicationConfiguration.class, "--server.port=0"); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - String port = context.getEnvironment().getProperty("local.server.port"); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/uppercase,lowercase,reverse"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("desserts"); - } - - - @SpringBootApplication - protected static class ApplicationConfiguration { - - @Bean - public Function uppercase() { - return s -> s.toUpperCase(); - } - - @Bean - public Function lowercase() { - return s -> s.toLowerCase(); - } - - @Bean - public Function reverse() { - return s -> new StringBuilder(s).reverse().toString(); - } - } - -} 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 deleted file mode 100644 index 4429d0ce4..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/FunctionEndpointInitializerTests.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2019-2022 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.function; - -import java.net.URI; -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionalSpringApplication; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.ResolvableType; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.util.UriComponentsBuilder; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; - -/** -* -* @author Oleg Zhurakousky -* @author Chris Bono -* @since 2.1 -*/ -public class FunctionEndpointInitializerTests { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void testEmptyBodyRequestParameters() throws Exception { - int port = startServerAndWaitForPort(BeansConfiguration.class, false); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - Map params = new HashMap<>(); - params.put("fname", "Jim"); - params.put("lname", "Lahey"); - - HttpHeaders headers = new HttpHeaders(); - headers.set("Accept", "application/json"); - HttpEntity entity = new HttpEntity(headers); - - String urlTemplate = UriComponentsBuilder.fromHttpUrl("http://localhost:" + port + "/nullPayload") - .queryParam("fname", "Jim").queryParam("lname", "Lahey").encode().toUriString(); - - ResponseEntity response = testRestTemplate.exchange(urlTemplate, HttpMethod.GET, entity, String.class); - String res = response.getBody(); - assertThat(res).contains("Jim"); - assertThat(res).contains("Lahey"); - } - - @Test - public void testNonExistingFunction() throws Exception { - int port = startServerAndWaitForPort(ApplicationConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/foo"), "stressed", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - @Test - public void testConsumerMapping() throws Exception { - int port = startServerAndWaitForPort(ConsumerConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/uppercase"), "stressed", String.class); - assertThat(response.getBody()).isNull(); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - } - - @Test - public void testSingleFunctionMapping() throws Exception { - int port = startServerAndWaitForPort(ApplicationConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/uppercase"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("STRESSED"); - response = testRestTemplate.postForEntity(new URI("http://localhost:" + port + "/reverse"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("desserts"); - } - - @Test - public void testCompositionFunctionMapping() throws Exception { - int port = startServerAndWaitForPort(ApplicationConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/uppercase,lowercase,reverse"), "stressed", String.class); - assertThat(response.getBody()).isEqualTo("desserts"); - } - - @Test - public void testGetWithtFunction() throws Exception { - int port = startServerAndWaitForPort(ApplicationConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .getForEntity(new URI("http://localhost:" + port + "/reverse/stressed"), String.class); - System.out.println(); - assertThat(response.getBody()).isEqualTo("desserts"); - } - - @Test - public void testGetWithtSupplier() throws Exception { - int port = startServerAndWaitForPort(ApplicationConfiguration.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - ResponseEntity response = testRestTemplate - .getForEntity(new URI("http://localhost:" + port + "/supplier"), String.class); - assertThat(response.getBody()).isEqualTo("Jim Lahey"); - } - - private int startServerAndWaitForPort(Class primaryAppConfig, boolean functional) throws InterruptedException { - ConfigurableApplicationContext context = functional - ? FunctionalSpringApplication.run(primaryAppConfig, "--server.port=0") - : SpringApplication.run(primaryAppConfig, "--server.port=0"); - await() - .pollDelay(Duration.ofMillis(500)) - .pollInterval(Duration.ofMillis(500)) - .atMost(Duration.ofSeconds(3)) - .untilAsserted(() -> { - String port = context.getEnvironment().getProperty("local.server.port"); - assertThat(port).as("Unable to get 'local.server.port' - server may not have started up").isNotEmpty(); - }); - return Integer.valueOf(context.getEnvironment().getProperty("local.server.port")); - } - - private int startServerAndWaitForPort(Class primaryAppConfig) throws InterruptedException { - return this.startServerAndWaitForPort(primaryAppConfig, true); - } - - @SpringBootConfiguration - protected static class ConsumerConfiguration - implements ApplicationContextInitializer { - - public Consumer consume() { - return v -> System.out.println(v); - } - - @Override - public void initialize(GenericApplicationContext applicationContext) { - - applicationContext.registerBean("consume", FunctionRegistration.class, - () -> new FunctionRegistration<>(consume()) - .type(ResolvableType.forClassWithGenerics(Consumer.class, String.class).getType())); - } - - } - - @EnableAutoConfiguration - @Configuration - protected static class BeansConfiguration { - @Bean - public BiFunction, Map> nullPayload() { - return (p, h) -> { - return h; - }; - } - } - - - @SpringBootConfiguration - protected static class ApplicationConfiguration - implements ApplicationContextInitializer { - - public Supplier supplier() { - return () -> "Jim Lahey"; - } - - public Function uppercase() { - return s -> s.toUpperCase(); - } - - public Function lowercase() { - return s -> s.toLowerCase(); - } - - public Function reverse() { - return s -> { - return new StringBuilder(s).reverse().toString(); - }; - } - - @Override - public void initialize(GenericApplicationContext applicationContext) { - - applicationContext.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()) - .type(FunctionTypeUtils.functionType(String.class, String.class))); - applicationContext.registerBean("reverse", FunctionRegistration.class, - () -> new FunctionRegistration<>(reverse()) - .type(FunctionTypeUtils.functionType(String.class, String.class))); - applicationContext.registerBean("lowercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(lowercase()) - .type(FunctionTypeUtils.functionType(String.class, String.class))); - applicationContext.registerBean("supplier", FunctionRegistration.class, - () -> new FunctionRegistration<>(supplier()) - .type(FunctionTypeUtils.supplierType(String.class))); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/UserSubmittedTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/UserSubmittedTests.java deleted file mode 100644 index dfbe5413a..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/function/UserSubmittedTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2019-2022 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.function; - -import java.net.URI; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - * @since 2.1 - */ -public class UserSubmittedTests { - - @Test - public void testIssue274() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(Issue274Configuration.class, "--server.port=0"); - int port = context.getEnvironment().getProperty("local.server.port", Integer.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - Thread.sleep(200); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/echo"), "", String.class); - assertThat(response.getBody()).isNull(); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - public void testIssue274WithData() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(Issue274Configuration.class, "--server.port=0"); - int port = context.getEnvironment().getProperty("local.server.port", Integer.class); - TestRestTemplate testRestTemplate = new TestRestTemplate(); - Thread.sleep(200); - ResponseEntity response = testRestTemplate - .postForEntity(new URI("http://localhost:" + port + "/echo"), "hello", String.class); - assertThat(response.getBody()).isEqualTo("HELLO"); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - - @SpringBootApplication - protected static class Issue274Configuration { - - @Bean - public Function echo() { - return s -> s.toUpperCase(); - } - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/DefaultRouteTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/DefaultRouteTests.java deleted file mode 100644 index e441eb5d9..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/DefaultRouteTests.java +++ /dev/null @@ -1,85 +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.web.mvc; - -import java.net.URI; -import java.util.function.Function; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.DefaultRouteTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "") -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class DefaultRouteTests { - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Test - @Disabled("FIXME") - public void explicit() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/uppercase")).body("foo"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("FOO"); - } - - @Test - @Disabled("FIXME") - public void implicit() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.post(new URI("/")).body("foo"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("FOO"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean - public Function, Flux> uppercase() { - return flux -> flux.map(value -> value.toUpperCase()); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/GeneralIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/GeneralIntegrationTests.java deleted file mode 100644 index da20059df..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/GeneralIntegrationTests.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2023-2023 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.mvc; - -import java.net.URI; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; -/** - * - * @author Oleg Zhurakousky - */ -public class GeneralIntegrationTests { - - @Test - public void testMappedAndUnmappedDeleteFunction() throws Exception { - ApplicationContext context = SpringApplication.run(MultipleConsumerConfiguration.class, "--server.port=0", - "--spring.cloud.function.http.DELETE=consumer2;supplier;function|consumer1"); - String port = context.getEnvironment().getProperty("local.server.port"); - TestRestTemplate template = new TestRestTemplate(); - - ResponseEntity result = template.exchange( - RequestEntity.delete(new URI("http://localhost:" + port + "/consumer1")) - .build(), Void.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - - result = template.exchange( - RequestEntity.delete(new URI("http://localhost:" + port + "/consumer2")) - .build(), Void.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); - - result = template.exchange( - RequestEntity.delete(new URI("http://localhost:" + port + "/function,consumer1")) - .build(), Void.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); - - result = template.exchange( - RequestEntity.delete(new URI("http://localhost:" + port + "/supplier")) - .build(), Void.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - @Test - public void testMappedAndUnmappedPostPutFunction() throws Exception { - ApplicationContext context = SpringApplication.run(MultipleConsumerConfiguration.class, "--server.port=0", - "--spring.cloud.function.http.POST=consumer2;function;supplier;function|consumer1"); - String port = context.getEnvironment().getProperty("local.server.port"); - TestRestTemplate template = new TestRestTemplate(); - - ResponseEntity result = template.exchange(RequestEntity - .post(new URI("http://localhost:" + port + "/consumer1")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - - result = template.exchange(RequestEntity - .post(new URI("http://localhost:" + port + "/consumer2")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(result.getBody()).isNull(); - - result = template.exchange(RequestEntity - .post(new URI("http://localhost:" + port + "/function,consumer1")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(result.getBody()).isNull(); - - result = template.exchange(RequestEntity - .post(new URI("http://localhost:" + port + "/function")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - - result = template.exchange(RequestEntity - .post(new URI("http://localhost:" + port + "/supplier")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - - @EnableAutoConfiguration - protected static class MultipleConsumerConfiguration { - - @Bean - public Consumer consumer1() { - return v -> { }; - } - - @Bean - public Consumer consumer2() { - return v -> { }; - } - - @Bean - public Function function() { - return v -> v; - } - - @Bean - public Supplier supplier() { - return () -> ""; - } - } -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HeadersToMessageTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HeadersToMessageTests.java deleted file mode 100644 index 14c264aee..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HeadersToMessageTests.java +++ /dev/null @@ -1,109 +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.web.mvc; - -import java.net.URI; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.HeadersToMessageTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpEntity; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.main.web-application-type=servlet", - "spring.cloud.function.web.path=/functions" }) -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class HeadersToMessageTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void testBodyAndCustomHeaderFromMessagePropagation() throws Exception { - HttpEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/employee")) - .contentType(MediaType.APPLICATION_JSON) - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("{\"name\":\"Bob\",\"age\":25}"); - assertThat(postForEntity.getHeaders().containsKey("x-content-type")).isTrue(); - assertThat(postForEntity.getHeaders().get("x-content-type").get(0)) - .isEqualTo("application/xml"); - assertThat(postForEntity.getHeaders().get("foo").get(0)).isEqualTo("bar"); - } - - @Test - public void testHeadersPropagatedByDefault() throws Exception { - HttpEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/vanilla")) - .contentType(MediaType.APPLICATION_JSON) - .header("x-context-type", "rubbish") - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - assertThat(postForEntity.getBody()) - .isEqualTo("{\"name\":\"Bob\",\"age\":25,\"foo\":\"bar\"}"); - assertThat(postForEntity.getHeaders().containsKey("x-context-type")).isTrue(); - assertThat(postForEntity.getHeaders().get("x-context-type").get(0)) - .isEqualTo("rubbish"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean({ "employee" }) - public Function>, Message>> function() { - return request -> { - Message> message = MessageBuilder - .withPayload(request.getPayload()) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build(); - return message; - }; - } - - @Bean - public Function, Map> vanilla() { - return request -> { - Map message = new LinkedHashMap<>(request); - message.put("foo", "bar"); - return message; - }; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpDeleteIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpDeleteIntegrationTests.java deleted file mode 100644 index 834edd2da..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpDeleteIntegrationTests.java +++ /dev/null @@ -1,155 +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.web.mvc; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.mvc.HttpDeleteIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=servlet") -@ContextConfiguration(classes = {ApplicationConfiguration.class}) -public class HttpDeleteIntegrationTests { - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private ApplicationConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - public void testDeleteConsumer() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.delete(new URI("/deleteConsumer/123")) - .build(), Void.class); - - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); - } - - @Test - public void testDeleteConsumerWithParameters() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.delete(new URI("/deleteConsumerAsMessage/123?foo=bar")) - .build(), Void.class); - - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); - } - - @Test - public void testDeleteWithFunction() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.delete(new URI("/deleteFunction")) - .build(), Void.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - private List list = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - SpringApplication.run(HttpDeleteIntegrationTests.ApplicationConfiguration.class, - args); - } - - @Bean - public Function deleteFunction() { - return v -> { - assertThat(v).isEqualTo("123"); - System.out.println("Deleting: " + v); - return null; - }; - } - - - @Bean - public Consumer deleteConsumer() { - return v -> { - assertThat(v).isEqualTo("123"); - System.out.println("Deleting: " + v); - }; - } - - @Bean - public Consumer> deleteConsumerAsMessage() { - return v -> { - assertThat(v.getPayload()).isEqualTo("123"); - assertThat(((Map) v.getHeaders().get("http_request_param")).get("foo")).isEqualTo("bar"); - System.out.println("Deleting: " + v); - }; - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpGetIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpGetIntegrationTests.java deleted file mode 100644 index d1629d0ec..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpGetIntegrationTests.java +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2012-2023 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.mvc; - -import java.net.URI; -import java.net.URISyntaxException; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.HttpGetIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Chris Bono - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=servlet") -@ContextConfiguration(classes = { RestApplication.class, ApplicationConfiguration.class }) -@DirtiesContext -public class HttpGetIntegrationTests { - - private static final MediaType EVENT_STREAM = MediaType.TEXT_EVENT_STREAM; - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private ApplicationConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - public void staticResource() { - assertThat(this.rest.getForObject("/test.html", String.class)) - .contains("Test"); - } - - @Test - public void wordsSSE() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.get(new URI("/words")).accept(EVENT_STREAM).build(), - String.class).getBody()).isEqualTo(sse("foo", "bar")); - } - - @Test - public void wordsJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/words")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - @Disabled("Fix error handling") - public void errorJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/bang")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void word() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/word")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("foo"); - } - - @ParameterizedTest - @ValueSource(strings = {"[hello", "hello]", "[hello]"}) - void textContentTypeWithValueWrappedBracketsIsOk(String inputMessagePayloadValue) throws URISyntaxException { - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/echo")) - .contentType(MediaType.TEXT_PLAIN) - .body(inputMessagePayloadValue), String.class); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(postForEntity.getBody()).isEqualTo(inputMessagePayloadValue); - } - - @Test - public void foos() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/foos")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void getMore() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/get/more")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void bareWords() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/bareWords")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void timeoutJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/timeout")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[\"foo\"]"); - } - - @Test - public void emptyJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/empty")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[]"); - } - - @Test - public void sentences() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/sentences")).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptAny() throws Exception { - assertThat( - this.rest - .exchange(RequestEntity.get(new URI("/sentences")) - .accept(MediaType.ALL).build(), String.class) - .getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - } - - @Test - public void sentencesAcceptJson() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.get(new URI("/sentences")) - .accept(MediaType.APPLICATION_JSON).build(), - String.class); - assertThat(result.getBody()).isEqualTo("[[\"go\",\"home\"],[\"come\",\"back\"]]"); - assertThat(result.getHeaders().getContentType()) - .isGreaterThanOrEqualTo(MediaType.APPLICATION_JSON); - } - - @Test - @Disabled - public void sentencesAcceptSse() throws Exception { - Thread.sleep(1000); - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/sentences")).accept(EVENT_STREAM).build(), - String.class); - assertThat(result.getBody()) - .isEqualTo(sse("[\"go\",\"home\"]", "[\"come\",\"back\"]")); - assertThat(result.getHeaders().getContentType().isCompatibleWith(EVENT_STREAM)) - .isTrue(); - } - - @Test - public void postMoreFoo() { - assertThat(this.rest.getForObject("/post/more/foo", String.class)) - .isEqualTo("[\"(FOO)\"]"); - } - - @Test - public void uppercaseGet() { - assertThat(this.rest.getForObject("/uppercase/foo", String.class)) - .isEqualTo("[\"(FOO)\"]"); - } - - @Test - public void convertGet() { - assertThat(this.rest.getForObject("/wrap/123", String.class)) - .isEqualTo("[\"..123..\"]"); - } - - @Test - public void supplierFirst() { - assertThat(this.rest.getForObject("/not/a/function", String.class)) - .isEqualTo("[\"hello\"]"); - } - - @Test - public void convertGetJson() throws Exception { - assertThat(this.rest - .exchange(RequestEntity.get(new URI("/entity/321")) - .accept(MediaType.APPLICATION_JSON).build(), String.class) - .getBody()).isEqualTo("[{\"value\":321}]"); - } - - @Test - @Disabled - // this test is wrong since it is returning Flux while setting CT to TEXT_PLAIN. We can't convert it - public void compose() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .get(new URI("/concat,reverse/foo")).accept(MediaType.TEXT_PLAIN).build(), - String.class); - assertThat(result.getBody()).isEqualTo("oofoof"); - } - - private String sse(String... values) { - return "data:" + StringUtils.arrayToDelimitedString(values, "\n\ndata:") + "\n\n"; - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - private List list = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - SpringApplication.run(HttpGetIntegrationTests.ApplicationConfiguration.class, - args); - } - - @Bean - public Function, Flux> concat() { - return flux -> flux.map(v -> v + v); - } - - @Bean - public Function, Flux> reverse() { - return flux -> flux.log() - .map(value -> new StringBuilder(value.trim()).reverse().toString()); - } - - @Bean({ "uppercase", "post/more" }) - public Function, Flux> uppercase() { - return flux -> flux.log() - .map(value -> "(" + value.trim().toUpperCase() + ")"); - } - - @Bean - public Function, Flux> wrap() { - return flux -> flux.log().map(value -> ".." + value + ".."); - } - - @Bean - public Function, Flux>> entity() { - return flux -> flux.log() - .map(value -> Collections.singletonMap("value", value)); - } - - @Bean({ "words", "get/more" }) - public Supplier> words() { - return () -> Flux.just("foo", "bar"); - } - - @Bean - public Supplier word() { - return () -> "foo"; - } - - @Bean - public Function echo() { - return (input) -> input; - } - - @Bean - public Supplier> foos() { - return () -> Flux.just(new Foo("foo"), new Foo("bar")); - } - - @Bean - public Supplier> bareWords() { - return () -> Arrays.asList("foo", "bar"); - } - - @Bean - public Supplier> bang() { - return () -> Flux.fromArray(new String[] { "foo", "bar" }).map(value -> { - if (value.equals("bar")) { - throw new RuntimeException("Bar"); - } - return value; - }); - } - - @Bean - public Supplier> empty() { - return () -> Flux.fromIterable(Collections.emptyList()); - } - - @Bean("not/a/function") - public Supplier> supplier() { - return () -> Flux.just("hello"); - } - - @Bean("not/a") - public Function, Flux> function() { - return input -> Flux.just("bye"); - } - - @Bean - public Supplier> timeout() { - return () -> Flux.defer(() -> Flux.create(emitter -> { - emitter.next("foo"); - }).timeout(Duration.ofMillis(1000L), Flux.empty())); - } - - @Bean - public Supplier>> sentences() { - return () -> Flux.just(Arrays.asList("go", "home"), - Arrays.asList("come", "back")); - } - - @Bean - public Function, Map> sum() { - return valueMap -> valueMap.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, values -> values - .getValue().stream().mapToInt(Integer::parseInt).sum())); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpPostIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpPostIntegrationTests.java deleted file mode 100644 index a12c46dcf..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/HttpPostIntegrationTests.java +++ /dev/null @@ -1,466 +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.web.mvc; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.HttpPostIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=servlet") -@ContextConfiguration(classes = { RestApplication.class, ApplicationConfiguration.class }) -public class HttpPostIntegrationTests { - - @LocalServerPort - private int port; - - @Autowired - private TestRestTemplate rest; - - @Autowired - private ApplicationConfiguration test; - - @BeforeEach - public void init() { - this.test.list.clear(); - } - - @Test - @Disabled - public void qualifierFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/foos")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"[FOO]\"},{\"value\":\"[BAR]\"}]"); - } - - @Test - public void updates() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\", \"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isNull(); - } - - @Test - public void updatesJson() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/updates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo(null); - } - - @Test - public void addFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/addFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - assertThat(result.getBody()).isEqualTo(null); - } - - @Test - public void bareUpdates() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpdates")).contentType(MediaType.APPLICATION_JSON) - .body("[\"one\",\"two\"]"), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); - assertThat(this.test.list).hasSize(2); - } - - @Test - public void uppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void messages() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/messages")).contentType(MediaType.APPLICATION_JSON) - // Remove this when Spring 5.0.8 is used - .accept(MediaType.valueOf("application/stream+json")) - .header("x-foo", "bar").body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getHeaders().getFirst("x-foo")).isEqualTo("bar"); - assertThat(result.getHeaders()).doesNotContainKey("id"); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void headers() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/headers")).contentType(MediaType.APPLICATION_JSON) - // Remove this when Spring 5.0.8 is used - .accept(MediaType.valueOf("application/stream+json")) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getHeaders().getFirst("foo")).isEqualTo("bar"); - assertThat(result.getHeaders()).doesNotContainKey("id"); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void uppercaseSingleValue() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/uppercase")) - .contentType(MediaType.TEXT_PLAIN).body("foo"), - String.class); - // Result is multi-valued so it has to come out as an array - assertThat(result.getBody()).isEqualTo("[\"(FOO)\"]"); - } - - @Test - @Disabled("WebFlux would split the request body into lines: TODO make this work the same") - public void uppercasePlainText() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.post(new URI("/uppercase")) - .contentType(MediaType.TEXT_PLAIN).body("foo\nbar"), - String.class); - assertThat(result.getBody()).isEqualTo("(FOO)(BAR)"); - } - - @Test - public void uppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void uppercaseFoo() throws Exception { - // Single Foo can be parsed - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) - .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()).isEqualTo("[{\"value\":\"FOO\"}]"); - } - - @Test - public void bareUppercaseFoos() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) - .body("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void bareUppercaseFoo() throws Exception { - // Single Foo can be parsed and returns a single value if the function is defined - // that way - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUpFoos")).contentType(MediaType.APPLICATION_JSON) - .body("{\"value\":\"foo\"}"), String.class); - assertThat(result.getBody()).isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void bareUppercase() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/bareUppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void singleValuedText() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/bareUppercase")) - .contentType(MediaType.TEXT_PLAIN).body("foo"), - String.class); - assertThat(result.getBody()).isEqualTo("(FOO)"); - } - - @Test - public void transform() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/transform")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void postMore() throws Exception { - ResponseEntity result = this.rest.exchange(RequestEntity - .post(new URI("/post/more")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class); - assertThat(result.getBody()).isEqualTo("[\"(FOO)\",\"(BAR)\"]"); - } - - @Test - public void convertPost() throws Exception { - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/wrap")) - .contentType(MediaType.TEXT_PLAIN).body("123"), - String.class); - // Result is multi-valued so it has to come out as an array - assertThat(result.getBody()).isEqualTo("[\"..123..\"]"); - } - - @Test - public void convertPostJson() throws Exception { - // If you POST a single value to a Function,Flux> it can't - // determine if the output is single valued, so it has to send an array back - ResponseEntity result = this.rest - .exchange( - RequestEntity.post(new URI("/doubler")) - .contentType(MediaType.TEXT_PLAIN).body("123"), - String.class); - assertThat(result.getBody()).isEqualTo("[246]"); - } - - @Test - public void uppercaseJsonArray() throws Exception { - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/maps")) - .contentType(MediaType.APPLICATION_JSON) - // The new line in the middle is optional - .body("[{\"value\":\"foo\"},\n{\"value\":\"bar\"}]"), - String.class).getBody()) - .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void uppercaseSSE() throws Exception { - assertThat(this.rest.exchange(RequestEntity.post(new URI("/uppercase")).contentType(MediaType.APPLICATION_JSON) - .body("[\"foo\",\"bar\"]"), String.class).getBody()) - .isEqualTo(sse("(FOO)", "(BAR)")); - } - - @Test - public void sum() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/sum")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.MULTIPART_FORM_DATA).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - - @Test - public void multipart() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/sum")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.MULTIPART_FORM_DATA).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - - @Test - public void count() throws Exception { - List list = Arrays.asList("A", "B", "A"); - assertThat(this.rest.exchange( - RequestEntity.post(new URI("/count")).accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON).body(list), - String.class).getBody()).isEqualTo("{\"A\":2,\"B\":1}"); - } - - private String sse(String... values) { - return "[\"" + StringUtils.arrayToDelimitedString(values, "\",\"") + "\"]"; - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - private List list = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - SpringApplication.run(HttpPostIntegrationTests.ApplicationConfiguration.class, - args); - } - - @Bean({ "uppercase", "transform", "post/more" }) - public Function, Flux> uppercase() { - return flux -> flux.log() - .map(value -> "(" + value.trim().toUpperCase() + ")"); - } - - @Bean - public Function bareUppercase() { - return value -> "(" + value.trim().toUpperCase() + ")"; - } - - @Bean - public Function, Message> messages() { - return value -> MessageBuilder - .withPayload("(" + value.getPayload().trim().toUpperCase() + ")") - .copyHeaders(value.getHeaders()).build(); - } - - @Bean - public Function>, Flux>> headers() { - return flux -> flux.map(value -> MessageBuilder - .withPayload("(" + value.getPayload().trim().toUpperCase() + ")") - .setHeader("foo", "bar").build()); - } - - @Bean - public Function, Flux> upFoos() { - return flux -> flux.log() - .map(value -> new Foo(value.getValue().trim().toUpperCase())); - } - - @Bean - public Function bareUpFoos() { - return value -> new Foo(value.getValue().trim().toUpperCase()); - } - - @Bean - public Function, Flux> wrap() { - return flux -> flux.log().map(value -> ".." + value + ".."); - } - - @Bean - public Function, Flux> doubler() { - return flux -> flux.log().map(value -> 2 * value); - } - - @Bean - public Function>, Flux>> maps() { - return flux -> flux.map(value -> { - value.put("value", value.get("value").trim().toUpperCase()); - return value; - }); - } - - @Bean - @Qualifier("foos") - public Function qualifier() { - return value -> new Foo("[" + value.trim().toUpperCase() + "]"); - } - - @Bean - public Consumer> updates() { - return flux -> flux.subscribe(value -> this.list.add(value)); - } - - @Bean - public Consumer> addFoos() { - return flux -> flux.subscribe(value -> this.list.add(value.getValue())); - } - - @Bean - public Consumer bareUpdates() { - return value -> { - this.list.add(value); - }; - } - - @Bean("not/a") - public Function, Flux> function() { - return input -> Flux.just("bye"); - } - - @Bean - public Function, Map> sum() { - return valueMap -> valueMap.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, values -> values - .getValue().stream().mapToInt(Integer::parseInt).sum())); - } - - @Bean - public Function, Mono>> count() { - return flux -> flux.collect(HashMap::new, - (map, word) -> map.merge(word, 1, Integer::sum)); - } - - } - - public static class Foo { - - private String value; - - public Foo(String value) { - this.value = value; - } - - Foo() { - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/MultipartFileTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/MultipartFileTests.java deleted file mode 100644 index 5b35a86c4..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/MultipartFileTests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2012-2022 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.mvc; - -import java.net.URI; -import java.util.List; -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.json.JsonMapper; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.multipart.MultipartFile; - -import static org.assertj.core.api.Assertions.assertThat; -/** - * - * @author Oleg Zhurakousky - * @author Chris Bono - */ -public class MultipartFileTests { - - @Test - public void testMultipartFileUpload() throws Exception { - ApplicationContext context = SpringApplication.run(TestConfiguration.class, "--server.port=0"); - String port = context.getEnvironment().getProperty("local.server.port"); - JsonMapper mapper = context.getBean(JsonMapper.class); - TestRestTemplate template = new TestRestTemplate(); - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - map.add("file", new ClassPathResource("META-INF/spring.factories")); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.MULTIPART_FORM_DATA); - - HttpEntity> requestEntity = new HttpEntity>( - map, headers); - ResponseEntity result = template.exchange(new URI("http://localhost:" + port + "/uppercase"), - HttpMethod.POST, requestEntity, String.class); - List resultCollection = mapper.fromJson(result.getBody(), List.class); - assertThat(resultCollection.get(0)).isEqualTo("SPRING.FACTORIES"); - } - - @Test - public void testMultipartFilesUpload() throws Exception { - ApplicationContext context = SpringApplication.run(TestConfiguration.class, "--server.port=0"); - String port = context.getEnvironment().getProperty("local.server.port"); - JsonMapper mapper = context.getBean(JsonMapper.class); - TestRestTemplate template = new TestRestTemplate(); - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - map.add("fileA", new ClassPathResource("META-INF/spring.factories")); - map.add("fileB", new ClassPathResource("static/test.html")); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.MULTIPART_FORM_DATA); - - HttpEntity> requestEntity = new HttpEntity>( - map, headers); - ResponseEntity result = template.exchange(new URI("http://localhost:" + port + "/uppercase"), - HttpMethod.POST, requestEntity, String.class); - List resultCollection = mapper.fromJson(result.getBody(), List.class); - assertThat(resultCollection.get(0)).isEqualTo("SPRING.FACTORIES"); - assertThat(resultCollection.get(1)).isEqualTo("TEST.HTML"); - } - - @EnableAutoConfiguration - protected static class TestConfiguration { - - @Bean - public Function uppercase() { - return value -> { - return value.getOriginalFilename().toUpperCase(); - }; - } - } -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/PrefixTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/PrefixTests.java deleted file mode 100644 index d8b264cb9..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/PrefixTests.java +++ /dev/null @@ -1,103 +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.web.mvc; - -import java.net.URI; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.PrefixTests.TestConfiguration; -import org.springframework.cloud.function.web.util.HeaderUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.main.web-application-type=servlet", - "spring.cloud.function.web.path=/functions" }) -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class PrefixTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/functions/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @Test - public void missing() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - - @Test - public void uppercase() throws Exception { - ResponseEntity result = this.rest.exchange( - RequestEntity.get(new URI("/functions/uppercase/foo?nome=Doe&prenome=John")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean({ "words", "get/more" }) - public Supplier> words() { - return () -> Flux.fromArray(new String[] { "foo", "bar" }); - } - - @Bean - public Function, String[]> uppercase() { - return message -> { - assertThat(message.getPayload().equals("foo")); - Map httpParam = (Map) message.getHeaders().get(HeaderUtils.HTTP_REQUEST_PARAM); - assertThat(httpParam.get("nome")).isEqualTo("Doe"); - assertThat(httpParam.get("prenome")).isEqualTo("John"); - return new String[] { "foo", "bar" }; - }; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/RoutingFunctionTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/RoutingFunctionTests.java deleted file mode 100644 index 53c90d0b2..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/RoutingFunctionTests.java +++ /dev/null @@ -1,259 +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.web.mvc; - -import java.net.URI; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.context.FunctionProperties; -import org.springframework.cloud.function.context.config.RoutingFunction; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.RoutingFunctionTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.main.web-application-type=servlet", - "spring.cloud.function.web.path=/functions", - "spring.cloud.function.routing.enabled=true"}) -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class RoutingFunctionTests { - - @Autowired - private TestRestTemplate rest; - - @Autowired - private FunctionProperties functionProperties; - - - @Test - @DirtiesContext - public void testFunctionMessage() throws Exception { - - HttpEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.APPLICATION_JSON) - .header("spring.cloud.function.definition", "employee") - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("{\"name\":\"Bob\",\"age\":25}"); - assertThat(postForEntity.getHeaders().containsKey("x-content-type")).isTrue(); - assertThat(postForEntity.getHeaders().get("x-content-type").get(0)) - .isEqualTo("application/xml"); - assertThat(postForEntity.getHeaders().get("foo").get(0)).isEqualTo("bar"); - } - - @Test - @DirtiesContext - public void testFunctionPrimitive() throws Exception { - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.TEXT_PLAIN) - .header("spring.cloud.function.definition", "echo") - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.TEXT_PLAIN) - .header("spring.cloud.function.definition", "echo") - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - - assertThat(postForEntity.getBody()).isEqualTo("{\"name\":\"Bob\",\"age\":25}"); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - @DirtiesContext - @Disabled // not sure if this test is correct. Why does ? has to be assumed as String? - public void testFluxFunctionPrimitive() throws Exception { - this.functionProperties.setDefinition("fluxuppercase"); - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.TEXT_PLAIN) - .body("[\"hello\", \"bye\"]"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("[\"HELLO\", \"BYE\"]"); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - - postForEntity = this.rest.exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.TEXT_PLAIN) - .body("hello1"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("HELLO1"); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - -// postForEntity = this.rest.exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) -// .contentType(MediaType.TEXT_PLAIN) -// .body("hello2"), String.class); -// assertThat(postForEntity.getBody()).isEqualTo("HELLO2"); -// assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - @DirtiesContext - public void testFluxFunctionPrimitiveArray() throws Exception { - this.functionProperties.setDefinition("fluxuppercase"); - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.APPLICATION_JSON) - .body(new String[] {"a", "b", "c"}), String.class); - assertThat(postForEntity.getBody()).isEqualTo("[\"A\",\"B\",\"C\"]"); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - @DirtiesContext - @Disabled - public void testFluxConsumer() throws Exception { - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.APPLICATION_JSON) - .header("function.name", "fluxconsumer") - .body(new String[] {"a", "b", "c"}), String.class); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - - } - - - @Test - @DirtiesContext - @Disabled - public void testFunctionPojo() throws Exception { - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.APPLICATION_JSON) - .header("function.name", "echoPojo") - .body("{\"value\":\"foo\"}"), String.class); - assertThat(postForEntity.getBody()).isEqualTo("{\"foo\":{\"value\":\"foo\"},\"value\":\"bar\"}"); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @Test - @DirtiesContext - @Disabled - public void testConsumerMessage() throws Exception { - ResponseEntity postForEntity = this.rest - .exchange(RequestEntity.post(new URI("/functions/" + RoutingFunction.FUNCTION_NAME)) - .contentType(MediaType.TEXT_PLAIN) - .header("spring.cloud.function.definition", "messageConsumer") - .body("{\"name\":\"Bob\",\"age\":25}"), String.class); - assertThat(postForEntity.getStatusCode()).isEqualTo(HttpStatus.OK); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean({ "employee" }) - public Function>, Message>> function() { - return request -> { - Message> message = MessageBuilder - .withPayload(request.getPayload()) - .setHeader("X-Content-Type", "application/xml") - .setHeader("foo", "bar").build(); - return message; - }; - } - - @Bean - public Consumer> messageConsumer() { - return value -> System.out.println("Value: " + value); - } - - @Bean - public Function echo() { - return v -> v; - } - - @Bean - public Function, Flux> fluxuppercase() { - return v -> v.map(s -> { - System.out.println(s); - return s.toUpperCase(); - }); - } - - @Bean - public Consumer> fluxconsumer() { - return flux -> flux.doOnNext(s -> { - System.out.println("Received: " + s); - }).subscribe(); - } - - @Bean - public Function echoPojo() { - return v -> { - Bar bar = new Bar(); - bar.setFoo(v); - bar.setValue("bar"); - return bar; - }; - } - - } - - public static class Foo { - private String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - - public static class Bar { - private Foo foo; - private String value; - public Foo getFoo() { - return foo; - } - public void setFoo(Foo foo) { - this.foo = foo; - } - public String getValue() { - return value; - } - public void setValue(String value) { - this.value = value; - } - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/SingletonTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/SingletonTests.java deleted file mode 100644 index 5636d5171..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/mvc/SingletonTests.java +++ /dev/null @@ -1,100 +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.web.mvc; - -import java.net.URI; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.mvc.SingletonTests.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ContextConfiguration(classes = { RestApplication.class, TestConfiguration.class }) -public class SingletonTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")).build(), String.class); - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]"); - } - - @EnableAutoConfiguration - @org.springframework.boot.test.context.TestConfiguration - protected static class TestConfiguration { - - @Bean - public static BeanDefinitionRegistryPostProcessor processor() { - return new BeanDefinitionRegistryPostProcessor() { - - @Override - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) - throws BeansException { - } - - @Override - public void postProcessBeanDefinitionRegistry( - BeanDefinitionRegistry registry) throws BeansException { - // Simulates what happens when you add a compiled function - RootBeanDefinition beanDefinition = new RootBeanDefinition( - MySupplier.class); - registry.registerBeanDefinition("words", beanDefinition); - } - }; - } - - } - - static class MySupplier implements Supplier> { - - @Override - public Flux get() { - return Flux.just("foo", "bar"); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationIntegrationTests.java deleted file mode 100644 index f2cfe400d..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationIntegrationTests.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2018-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.web.source; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.function.web.TestSocketUtils; -import org.springframework.cloud.function.web.source.FunctionAutoConfigurationIntegrationTests.ApplicationConfiguration; -import org.springframework.cloud.function.web.source.FunctionAutoConfigurationIntegrationTests.RestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(classes = { RestConfiguration.class, - ApplicationConfiguration.class }, webEnvironment = WebEnvironment.DEFINED_PORT, properties = { - "spring.cloud.function.web.export.sink.url=http://localhost:${server.port}", - "spring.cloud.function.web.export.source.url=http://localhost:${server.port}", - "spring.cloud.function.web.export.sink.name=origin|uppercase" - // "spring.cloud.function.web.export.debug=true" - }) -@Disabled -public class FunctionAutoConfigurationIntegrationTests { - - @Autowired - private SupplierExporter forwarder; - - @Autowired - private RestConfiguration app; - - @BeforeAll - public static void init() { - System.setProperty("server.port", "" + TestSocketUtils.findAvailableTcpPort()); - } - - @AfterAll - public static void close() { - System.clearProperty("server.port"); - } - - @Test - public void copiesMessages() throws Exception { - int count = 0; - while (this.forwarder.isRunning() && count++ < 10) { - Thread.sleep(20); - } - // It completed - assertThat(this.forwarder.isOk()).isTrue(); - assertThat(this.app.inputs).contains("\"HELLO\""); - assertThat(this.app.inputs).contains("\"WORLD\""); - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - } - - @TestConfiguration - @RestController - public static class RestConfiguration { - - private static Log logger = LogFactory.getLog(RestConfiguration.class); - - private List inputs = new ArrayList<>(); - - private Iterator outputs = Arrays.asList("hello", "world").iterator(); - - @GetMapping("/") - ResponseEntity home() { - logger.info("HOME"); - if (this.outputs.hasNext()) { - return ResponseEntity.ok(this.outputs.next()); - } - return ResponseEntity.notFound().build(); - } - - @PostMapping("/") - void accept(@RequestBody String body) { - logger.info("ACCEPT"); - this.inputs.add(body); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationWithRetriesIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationWithRetriesIntegrationTests.java deleted file mode 100644 index 4ded82a1c..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/FunctionAutoConfigurationWithRetriesIntegrationTests.java +++ /dev/null @@ -1,137 +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.web.source; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.function.web.TestSocketUtils; -import org.springframework.cloud.function.web.source.FunctionAutoConfigurationWithRetriesIntegrationTests.ApplicationConfiguration; -import org.springframework.cloud.function.web.source.FunctionAutoConfigurationWithRetriesIntegrationTests.RestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - * - */ -@SpringBootTest(classes = { RestConfiguration.class, - ApplicationConfiguration.class }, - webEnvironment = WebEnvironment.DEFINED_PORT, properties = { - "spring.cloud.function.web.export.sink.url=http://localhost:${server.port}", - "spring.cloud.function.web.export.source.url=http://localhost:${server.port}", - "spring.cloud.function.web.export.sink.name=origin|uppercase", - "spring.cloud.function.web.export.debug=true"}) -public class FunctionAutoConfigurationWithRetriesIntegrationTests { - - @Autowired - private SupplierExporter forwarder; - - @Autowired - private RestConfiguration app; - - @BeforeAll - public static void init() { - System.setProperty("server.port", "" + TestSocketUtils.findAvailableTcpPort()); - } - - @AfterAll - public static void close() { - System.clearProperty("server.port"); - } - - @Test - @Disabled - public void copiesMessages() throws Exception { - int count = 0; - while (this.forwarder.isRunning() && count++ < 30) { - Thread.sleep(200); - } - // It completed - assertThat(this.forwarder.isOk()).isTrue(); - assertThat(this.forwarder.isRunning()).isFalse(); - assertThat(this.app.inputs.size()).isEqualTo(4); - assertThat(this.app.inputs).contains("2"); - assertThat(this.app.inputs).contains("4"); - assertThat(this.app.inputs).contains("6"); - assertThat(this.app.inputs).contains("8"); - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - @Bean - public Function uppercase() { - return value -> value.toUpperCase(); - } - - } - - @TestConfiguration - @RestController - public static class RestConfiguration { - - @Autowired - private SupplierExporter forwarder; - - private static Log logger = LogFactory.getLog(RestConfiguration.class); - - private List inputs = new ArrayList<>(); - - private int counter; - - @GetMapping("/") - ResponseEntity home() { - logger.info("HOME"); - if (++counter % 2 == 0 && counter < 10) { - return ResponseEntity.ok(String.valueOf(counter)); - } - if (counter >= 10) { - forwarder.stop(); - } - return ResponseEntity.notFound().build(); - } - - @PostMapping("/") - void accept(@RequestBody String body) { - logger.info("ACCEPT"); - this.inputs.add(body); - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/SourceAutoConfigurationIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/SourceAutoConfigurationIntegrationTests.java deleted file mode 100644 index 600bc728c..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/SourceAutoConfigurationIntegrationTests.java +++ /dev/null @@ -1,73 +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.web.source; - -import java.util.function.Supplier; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.function.web.source.SourceAutoConfigurationIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -// @formatter:off -@SpringBootTest(webEnvironment = WebEnvironment.NONE, - properties = "spring.cloud.function.web.export.sink.url=https://nosuchhost") -// @formatter:on -@ContextConfiguration(classes = { ApplicationConfiguration.class }) -@Disabled -public class SourceAutoConfigurationIntegrationTests { - - @Autowired - private SupplierExporter forwarder; - - @Test - public void fails() throws Exception { - int count = 0; - while (this.forwarder.isRunning() && count++ < 1000) { - Thread.sleep(50); - } - // It completed - assertThat(this.forwarder.isRunning()).isFalse(); - // But failed - assertThat(this.forwarder.isOk()).isFalse(); - } - - @EnableAutoConfiguration - @TestConfiguration - public static class ApplicationConfiguration { - - @Bean - public Supplier word() { - return () -> "foo"; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/WebAppIntegrationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/WebAppIntegrationTests.java deleted file mode 100644 index a768fc537..000000000 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/source/WebAppIntegrationTests.java +++ /dev/null @@ -1,110 +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.web.source; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.function.web.RestApplication; -import org.springframework.cloud.function.web.TestSocketUtils; -import org.springframework.cloud.function.web.source.WebAppIntegrationTests.ApplicationConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -@SpringBootTest(classes = { RestApplication.class, ApplicationConfiguration.class }, - webEnvironment = WebEnvironment.DEFINED_PORT, properties = { - "spring.main.web-application-type=reactive", - "spring.cloud.function.web.export.sink.url=http://localhost:${server.port}/values", - // manually so we know the webapp is listening when we start - "spring.cloud.function.web.export.autoStartup=false" }) -public class WebAppIntegrationTests { - - private static Log logger = LogFactory.getLog(WebAppIntegrationTests.class); - - @Autowired - private SupplierExporter forwarder; - - @Autowired - private ApplicationConfiguration app; - - @BeforeAll - public static void init() { - System.setProperty("server.port", "" + TestSocketUtils.findAvailableTcpPort()); - } - - @AfterAll - public static void close() { - System.clearProperty("server.port"); - } - - @Test - @Disabled - public void posts() throws Exception { - this.forwarder.start(); - this.app.latch.await(10, TimeUnit.SECONDS); - assertThat(this.app.values).hasSize(1); - } - - @EnableAutoConfiguration - @TestConfiguration - @RestController - public static class ApplicationConfiguration { - - private List values = new ArrayList<>(); - - private CountDownLatch latch = new CountDownLatch(1); - - @Bean - public Supplier word() { - return () -> "foo"; - } - - // An endpoint to catch the values being exported - @PostMapping("/values") - public String value(@RequestBody String body) { - logger.info("Body: " + body); - this.values.add(body); - this.latch.countDown(); - return "ok"; - } - - } - -} diff --git a/spring-cloud-function-web/src/test/resources/static/test.html b/spring-cloud-function-web/src/test/resources/static/test.html deleted file mode 100644 index d64d7739a..000000000 --- a/spring-cloud-function-web/src/test/resources/static/test.html +++ /dev/null @@ -1,3 +0,0 @@ - -Test - diff --git a/spring-cloud-starter-function-web/pom.xml b/spring-cloud-starter-function-web/pom.xml deleted file mode 100644 index bf78f1fd8..000000000 --- a/spring-cloud-starter-function-web/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - .. - - spring-cloud-starter-function-web - spring-cloud-starter-starter-function-web - Spring Cloud Starter - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-web - - - diff --git a/spring-cloud-starter-function-webflux/pom.xml b/spring-cloud-starter-function-webflux/pom.xml deleted file mode 100644 index c64452d12..000000000 --- a/spring-cloud-starter-function-webflux/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-function-parent - 4.1.0-SNAPSHOT - - spring-cloud-starter-function-webflux - spring-cloud-starter-function-webflux - Spring Cloud Starter - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-webflux - - - diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml deleted file mode 100644 index f0be38384..000000000 --- a/src/checkstyle/checkstyle-suppressions.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/supplemental-ui/partials/nav-search.hbs b/supplemental-ui/partials/nav-search.hbs new file mode 100644 index 000000000..5e3795528 --- /dev/null +++ b/supplemental-ui/partials/nav-search.hbs @@ -0,0 +1,11 @@ +{{#if env.ALGOLIA_API_KEY}} +

+{{/if}} diff --git a/supplemental-ui/partials/search.hbs b/supplemental-ui/partials/search.hbs new file mode 100644 index 000000000..384e505f6 --- /dev/null +++ b/supplemental-ui/partials/search.hbs @@ -0,0 +1,27 @@ + +{{#if env.ALGOLIA_API_KEY}} + + + + + + + + +{{/if}} From fae0923e418b81f77e89537167cf3185efed5daa Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Sep 2023 18:36:03 +0200 Subject: [PATCH 11/31] Update deploy-docs.yml --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 31c46dcb0..b1318c8d5 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -38,7 +38,7 @@ jobs: run: | ./mvnw --no-transfer-progress -B antora - name: Publish Docs - uses: rwinch/spring-doc-actions/rsync-antora-reference@httpdocs-path + uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.11 with: docs-username: ${{ secrets.DOCS_USERNAME }} docs-host: ${{ secrets.DOCS_HOST }} From 51d2dd20eb3c6ee0d2e44eb9f5746407796267b0 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Fri, 22 Sep 2023 16:16:36 -0400 Subject: [PATCH 12/31] Adds antora extension and updates ui version --- antora-playbook.yml | 3 ++- pom.xml | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index 29692089d..d289efe05 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -7,6 +7,7 @@ antora: - '@antora/atlas-extension' - require: '@springio/antora-extensions/root-component-extension' root_component_name: 'cloud-function' + - '@springio/antora-extensions/static-page-extension' site: title: Spring Cloud Function url: https://docs.spring.io/spring-cloud-function/reference @@ -36,7 +37,7 @@ urls: redirect_facility: httpd ui: bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.2/ui-bundle.zip snapshot: true runtime: log: diff --git a/pom.xml b/pom.xml index ef9765fb4..ae27a4203 100644 --- a/pom.xml +++ b/pom.xml @@ -43,8 +43,15 @@ 9d489079e5ec46dbb238909fee5c9c29 WB1FQYI187 - springcloudfunction + springdocs + + @antora/atlas-extension@1.0.0-alpha.1 + @antora/collector-extension@1.0.0-alpha.3 + @asciidoctor/tabs@1.0.0-beta.3 + @springio/antora-extensions@1.6.0 + @springio/asciidoctor-extensions@1.0.0-alpha.9 + From 9f9fdb625fa6f9c9824b1f7dec085e813d8e7d2f Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 28 Sep 2023 13:23:33 +0200 Subject: [PATCH 13/31] Fix tag wildcards. --- antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index d289efe05..5f0e8b016 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -20,7 +20,7 @@ content: # Refname matching: # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ branches: [ main ] - tags: [ '({4..9}).+({1..9}).+({0..9})?(-{RC,M}+({0..9}))', '!4.1.0-M1' ] + tags: [ 'v{4..9}.+({1..9}).+({0..9})?(-{RC,M}*)', '!v4.1.0-M1' ] start_path: docs asciidoc: attributes: From 475aa83bedc761417b963ce66ba6403a5e7978a6 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 12 Dec 2023 11:21:42 -0500 Subject: [PATCH 14/31] Update deploy-docs.yml --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index b1318c8d5..2438c114c 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -38,7 +38,7 @@ jobs: run: | ./mvnw --no-transfer-progress -B antora - name: Publish Docs - uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.11 + uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.13 with: docs-username: ${{ secrets.DOCS_USERNAME }} docs-host: ${{ secrets.DOCS_HOST }} From 4e44a915f68263b88e4531e8aaf2b0e0e16def96 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 26 Mar 2024 15:15:56 -0400 Subject: [PATCH 15/31] Update antora-playbook.yml --- antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index 5f0e8b016..d6aa8ad30 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -37,7 +37,7 @@ urls: redirect_facility: httpd ui: bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.2/ui-bundle.zip + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip snapshot: true runtime: log: From fe6677e39ef5851545c4f5f1b1bd2b883ef23d7e Mon Sep 17 00:00:00 2001 From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:04:54 -0400 Subject: [PATCH 16/31] Upgrading antora --- .gitignore | 2 +- antora-playbook.yml | 10 ++------- package.json | 10 +++++++++ pom.xml | 54 ++++++--------------------------------------- 4 files changed, 20 insertions(+), 56 deletions(-) create mode 100644 package.json diff --git a/.gitignore b/.gitignore index 6be8a4a16..360a846b6 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,5 @@ src/ant/.ant-targets-upload-dist.xml node node_modules build -package.json +docs/package.json package-lock.json diff --git a/antora-playbook.yml b/antora-playbook.yml index d6aa8ad30..82a20c241 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -1,13 +1,7 @@ antora: extensions: - - '@springio/antora-extensions/partial-build-extension' - - require: '@springio/antora-extensions/latest-version-extension' - - require: '@springio/antora-extensions/inject-collector-cache-config-extension' - - '@antora/collector-extension' - - '@antora/atlas-extension' - - require: '@springio/antora-extensions/root-component-extension' + - require: '@springio/antora-extensions' root_component_name: 'cloud-function' - - '@springio/antora-extensions/static-page-extension' site: title: Spring Cloud Function url: https://docs.spring.io/spring-cloud-function/reference @@ -37,7 +31,7 @@ urls: redirect_facility: httpd ui: bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.15/ui-bundle.zip snapshot: true runtime: log: diff --git a/package.json b/package.json new file mode 100644 index 000000000..c3570e2f8 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "antora": "3.2.0-alpha.4", + "@antora/atlas-extension": "1.0.0-alpha.2", + "@antora/collector-extension": "1.0.0-alpha.3", + "@asciidoctor/tabs": "1.0.0-beta.6", + "@springio/antora-extensions": "1.11.1", + "@springio/asciidoctor-extensions": "1.0.0-alpha.10" + } +} diff --git a/pom.xml b/pom.xml index ae27a4203..ad17881ce 100644 --- a/pom.xml +++ b/pom.xml @@ -3,9 +3,13 @@ 4.0.0 - org.springframework.cloud spring-cloud-function-docs-build - 0.0.1-SNAPSHOT + ${parent.version} + + org.springframework.cloud + spring-cloud-function-parent + 4.1.3-SNAPSHOT + Spring Cloud Function Docs Build Builds Spring Cloud Function Docs. @@ -22,56 +26,12 @@ https://github.com/spring-cloud/spring-cloud-function/issues - - 0.0.3 - - - - io.spring.maven.antora + org.antora antora-maven-plugin - ${io.spring.maven.antora-version} - true - - - - - - - - 9d489079e5ec46dbb238909fee5c9c29 - WB1FQYI187 - springdocs - - - @antora/atlas-extension@1.0.0-alpha.1 - @antora/collector-extension@1.0.0-alpha.3 - @asciidoctor/tabs@1.0.0-beta.3 - @springio/antora-extensions@1.6.0 - @springio/asciidoctor-extensions@1.0.0-alpha.9 - - - - - - spring-snapshot - https://repo.spring.io/snapshot - - true - - - false - - - - spring-milestone - https://repo.spring.io/milestone - - - From 362a7b64207f8e75467da6e8bac5766074a63ccc Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 11 Jul 2024 14:18:55 +0200 Subject: [PATCH 17/31] Upgrade to 4.1.4-SNAPSHOT. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ad17881ce..6aef3e152 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-function-parent - 4.1.3-SNAPSHOT + 4.1.4-SNAPSHOT Spring Cloud Function Docs Build From a95bfd2b6b32b252bd9ac40bde7937e94d103fa0 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 11 Jul 2024 15:25:28 +0200 Subject: [PATCH 18/31] Upgrade to 4.1.4-SNAPSHOT. --- .github/workflows/deploy-docs.yml | 2 +- pom.xml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 2438c114c..51b0f34f1 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -36,7 +36,7 @@ jobs: echo BUILD_VERSION=$BUILD_VERSION >> $GITHUB_ENV - name: Run Antora run: | - ./mvnw --no-transfer-progress -B antora + ./mvnw --no-transfer-progress -B antora:antora - name: Publish Docs uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.13 with: diff --git a/pom.xml b/pom.xml index 6aef3e152..7320f5031 100644 --- a/pom.xml +++ b/pom.xml @@ -34,4 +34,21 @@ + + + + spring-snapshot + https://repo.spring.io/snapshot + + true + + + false + + + + spring-milestone + https://repo.spring.io/milestone + + From ce75c0afd344299c92d73c7c98ab287cbfd8d61d Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Mon, 15 Jul 2024 15:24:18 +0200 Subject: [PATCH 19/31] Use docs profile in GH actions. --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 51b0f34f1..f468738cf 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -36,7 +36,7 @@ jobs: echo BUILD_VERSION=$BUILD_VERSION >> $GITHUB_ENV - name: Run Antora run: | - ./mvnw --no-transfer-progress -B antora:antora + ./mvnw --no-transfer-progress -B antora -Pdocs - name: Publish Docs uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.13 with: From 5e74cfe4a05091b882779327e05f252428275484 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 4 Sep 2024 16:00:46 -0400 Subject: [PATCH 20/31] Adds 4.1.x branch --- antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index 82a20c241..78a325d91 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -13,7 +13,7 @@ content: - url: https://github.com/spring-cloud/spring-cloud-function # Refname matching: # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ - branches: [ main ] + branches: [ main, 4.1.x ] tags: [ 'v{4..9}.+({1..9}).+({0..9})?(-{RC,M}*)', '!v4.1.0-M1' ] start_path: docs asciidoc: From c655cf99f647ea13fc8b138692fa5200e97d61f0 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 11 Sep 2025 18:09:48 -0400 Subject: [PATCH 21/31] Updates tags to build and antora-ui-version --- antora-playbook.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index 78a325d91..9dc0b607e 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -14,7 +14,7 @@ content: # Refname matching: # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ branches: [ main, 4.1.x ] - tags: [ 'v{4..9}.+({1..9}).+({0..9})?(-{RC,M}*)', '!v4.1.0-M1' ] + tags: [ 'v{4..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!v4.1.0-M1', '!v4.0.*' ] start_path: docs asciidoc: attributes: @@ -31,7 +31,7 @@ urls: redirect_facility: httpd ui: bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.15/ui-bundle.zip + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip snapshot: true runtime: log: From c0f73aa2a0e406cdc36ab51b6b04d11f38b2cb36 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 11 Sep 2025 18:10:15 -0400 Subject: [PATCH 22/31] Updates .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 360a846b6..64ce0fa6c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ node_modules build docs/package.json package-lock.json +.flattened-pom.xml \ No newline at end of file From 100e6c788b6932bed0fd788732d136cec96a4385 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 11 Sep 2025 18:34:13 -0400 Subject: [PATCH 23/31] Updates branches to build --- antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora-playbook.yml b/antora-playbook.yml index 9dc0b607e..863595b87 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -13,7 +13,7 @@ content: - url: https://github.com/spring-cloud/spring-cloud-function # Refname matching: # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ - branches: [ main, 4.1.x ] + branches: [ main, 4.3.x, 4.2.x ] tags: [ 'v{4..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!v4.1.0-M1', '!v4.0.*' ] start_path: docs asciidoc: From cbce10c4e2e919e09be02cf297c45f1571173474 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:10:41 +0000 Subject: [PATCH 24/31] Bump @springio/asciidoctor-extensions Bumps [@springio/asciidoctor-extensions](https://github.com/spring-io/asciidoctor-extensions) from 1.0.0-alpha.10 to 1.0.0-alpha.18. - [Changelog](https://github.com/spring-io/asciidoctor-extensions/blob/main/CHANGELOG.adoc) - [Commits](https://github.com/spring-io/asciidoctor-extensions/compare/v1.0.0-alpha.10...v1.0.0-alpha.18) --- updated-dependencies: - dependency-name: "@springio/asciidoctor-extensions" dependency-version: 1.0.0-alpha.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3570e2f8..344db614e 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,6 @@ "@antora/collector-extension": "1.0.0-alpha.3", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.11.1", - "@springio/asciidoctor-extensions": "1.0.0-alpha.10" + "@springio/asciidoctor-extensions": "1.0.0-alpha.18" } } From db0577809b8476195a894f616eb0046b6f881fab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:10:48 +0000 Subject: [PATCH 25/31] Bump @springio/antora-extensions from 1.11.1 to 1.14.11 Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.11.1 to 1.14.11. - [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc) - [Commits](https://github.com/spring-io/antora-extensions/compare/v1.11.1...v1.14.11) --- updated-dependencies: - dependency-name: "@springio/antora-extensions" dependency-version: 1.14.11 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3570e2f8..73183c202 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "@antora/atlas-extension": "1.0.0-alpha.2", "@antora/collector-extension": "1.0.0-alpha.3", "@asciidoctor/tabs": "1.0.0-beta.6", - "@springio/antora-extensions": "1.11.1", + "@springio/antora-extensions": "1.14.11", "@springio/asciidoctor-extensions": "1.0.0-alpha.10" } } From a86702fd33e4725fc3a6e763100e5479bbcaf695 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:39:43 +0000 Subject: [PATCH 26/31] Bump @antora/collector-extension from 1.0.0-alpha.3 to 1.0.3 --- updated-dependencies: - dependency-name: "@antora/collector-extension" dependency-version: 1.0.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73183c202..5a29b9c33 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "dependencies": { "antora": "3.2.0-alpha.4", "@antora/atlas-extension": "1.0.0-alpha.2", - "@antora/collector-extension": "1.0.0-alpha.3", + "@antora/collector-extension": "1.0.3", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.14.11", "@springio/asciidoctor-extensions": "1.0.0-alpha.10" From f1b9481fb6084cdc9bd76594ddc2197b1d196a68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:39:45 +0000 Subject: [PATCH 27/31] Bump antora from 3.2.0-alpha.4 to 3.2.0-alpha.11 --- updated-dependencies: - dependency-name: antora dependency-version: 3.2.0-alpha.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73183c202..765f9785c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "antora": "3.2.0-alpha.4", + "antora": "3.2.0-alpha.11", "@antora/atlas-extension": "1.0.0-alpha.2", "@antora/collector-extension": "1.0.0-alpha.3", "@asciidoctor/tabs": "1.0.0-beta.6", From 992d63c3a80ac423ffa71c31c2bd101ddf23eb2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:51:31 +0000 Subject: [PATCH 28/31] Bump @antora/atlas-extension from 1.0.0-alpha.2 to 1.0.0-alpha.5 --- updated-dependencies: - dependency-name: "@antora/atlas-extension" dependency-version: 1.0.0-alpha.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c00686db..80836ebda 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "dependencies": { "antora": "3.2.0-alpha.11", - "@antora/atlas-extension": "1.0.0-alpha.2", + "@antora/atlas-extension": "1.0.0-alpha.5", "@antora/collector-extension": "1.0.3", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.14.11", From 7d1371953702ee967606dad35d1102eed030402b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:28:20 +0000 Subject: [PATCH 29/31] Bump @springio/asciidoctor-extensions Bumps [@springio/asciidoctor-extensions](https://github.com/spring-io/asciidoctor-extensions) from 1.0.0-alpha.10 to 1.0.0-alpha.18. - [Changelog](https://github.com/spring-io/asciidoctor-extensions/blob/main/CHANGELOG.adoc) - [Commits](https://github.com/spring-io/asciidoctor-extensions/compare/v1.0.0-alpha.10...v1.0.0-alpha.18) --- updated-dependencies: - dependency-name: "@springio/asciidoctor-extensions" dependency-version: 1.0.0-alpha.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80836ebda..bafa987d1 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,6 @@ "@antora/collector-extension": "1.0.3", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.14.11", - "@springio/asciidoctor-extensions": "1.0.0-alpha.10" + "@springio/asciidoctor-extensions": "1.0.0-alpha.18" } } From 13782fc677c0c9243dba837e37649880ee31a7c9 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Sun, 17 May 2026 09:47:41 -0400 Subject: [PATCH 30/31] Upgrading parent pom and antora version --- package.json | 2 +- pom.xml | 105 ++++++++++++++++++++++++++++----------------------- 2 files changed, 58 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index 80836ebda..78293c991 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "antora": "3.2.0-alpha.11", + "antora": "3.2.0-alpha.12", "@antora/atlas-extension": "1.0.0-alpha.5", "@antora/collector-extension": "1.0.3", "@asciidoctor/tabs": "1.0.0-beta.6", diff --git a/pom.xml b/pom.xml index 7320f5031..d62c2a153 100644 --- a/pom.xml +++ b/pom.xml @@ -1,54 +1,63 @@ - - 4.0.0 - - spring-cloud-function-docs-build - ${parent.version} - - org.springframework.cloud - spring-cloud-function-parent - 4.1.4-SNAPSHOT - - - Spring Cloud Function Docs Build - Builds Spring Cloud Function Docs. - https://spring.io/projects/spring-cloud-function - - scm:git:https://github.com/spring-cloud/spring-cloud-function.git + 4.0.0 + spring-cloud-function-docs-build + ${parent.version} + + org.springframework.cloud + spring-cloud-function-parent + 5.0.2-SNAPSHOT + + Spring Cloud Function Docs Build + Builds Spring Cloud Function Docs. + https://spring.io/projects/spring-cloud-function + + scm:git:https://github.com/spring-cloud/spring-cloud-function.git - + scm:git:git@github.com:spring-cloud/spring-cloud-function.git - https://github.com/spring-cloud/spring-cloud-function - - - https://github.com/spring-cloud/spring-cloud-function/issues - - - - - - org.antora - antora-maven-plugin - - - - - - - spring-snapshot - https://repo.spring.io/snapshot - - true - - - false - - - - spring-milestone - https://repo.spring.io/milestone - - + https://github.com/spring-cloud/spring-cloud-function + + + https://github.com/spring-cloud/spring-cloud-function/issues + + + + + org.antora + antora-maven-plugin + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + true + false + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + false + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + true + false + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + false + + From ef3412288541706206e61822630af4254bb80cad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 19:44:46 +0000 Subject: [PATCH 31/31] Bump @springio/antora-extensions from 1.14.11 to 1.14.12 Bumps [@springio/antora-extensions](https://github.com/spring-io/antora-extensions) from 1.14.11 to 1.14.12. - [Changelog](https://github.com/spring-io/antora-extensions/blob/main/CHANGELOG.adoc) - [Commits](https://github.com/spring-io/antora-extensions/compare/v1.14.11...v1.14.12) --- updated-dependencies: - dependency-name: "@springio/antora-extensions" dependency-version: 1.14.12 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 209ff832c..8434c31b5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "@antora/atlas-extension": "1.0.0-alpha.5", "@antora/collector-extension": "1.0.3", "@asciidoctor/tabs": "1.0.0-beta.6", - "@springio/antora-extensions": "1.14.11", + "@springio/antora-extensions": "1.14.12", "@springio/asciidoctor-extensions": "1.0.0-alpha.18" } }

{EUh!tI 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 diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/mvnw b/spring-cloud-function-samples/function-sample-kotlin-web/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/mvnw.cmd b/spring-cloud-function-samples/function-sample-kotlin-web/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml b/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml deleted file mode 100644 index c067fc3c3..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - 4.0.0 - io.spring.sample - function-sample-kotlin-web - 0.0.1-SNAPSHOT - function-sample-kotlin-web - Demo project for Spring Cloud Function Web Kotlin integration - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - - org.springframework.boot - spring-boot-starter - - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.springframework.cloud - spring-cloud-function-kotlin - 4.1.0-SNAPSHOT - - - org.springframework.cloud - spring-cloud-function-web - 4.1.0-SNAPSHOT - - - org.springframework.cloud - spring-cloud-function-context - 4.1.0-SNAPSHOT - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/test/kotlin - - - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.jetbrains.kotlin - kotlin-maven-plugin - - - -Xjsr305=strict - - - spring - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - - - - - 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-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinApplication.kt b/spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinApplication.kt deleted file mode 100644 index 126ba69f0..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinApplication.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.kotlin - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication -import org.springframework.context.annotation.Bean -import java.util.function.Function -import org.springframework.cloud.function.context.FunctionCatalog -import kotlin.jvm.internal.Reflection -import kotlin.jvm.javaClass - -@SpringBootApplication -open class DemoKotlinApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinConfiguration.kt b/spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinConfiguration.kt deleted file mode 100644 index ca207e7fd..000000000 --- a/spring-cloud-function-samples/function-sample-kotlin-web/src/main/kotlin/com/example/kotlin/DemoKotlinConfiguration.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.kotlin - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication -import org.springframework.context.annotation.Bean -import java.util.function.Function -import org.springframework.context.annotation.Configuration - -@Configuration -class DemoKotlinConfiguration { - @Bean - fun uppercase(): (String) -> String { - return { it.toUpperCase() } - } -} - - - diff --git a/spring-cloud-function-samples/function-sample-kotlin-web/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-kotlin-web/src/main/resources/application.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-pof/build.gradle b/spring-cloud-function-samples/function-sample-pof/build.gradle deleted file mode 100644 index d62d81852..000000000 --- a/spring-cloud-function-samples/function-sample-pof/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -buildscript { - ext { - springBootVersion = '1.5.12.RELEASE' - wrapperVersion = '1.0.11.RELEASE' - } - repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/plugins-snapshot" } - maven { url "https://repo.spring.io/plugins-milestone" } - } - dependencies { - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'spring-boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "2.0.0.BUILD-SNAPSHOT" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile('org.springframework.cloud:spring-cloud-starter-function-web') - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample-pof/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-pof/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample-pof/gradlew.bat b/spring-cloud-function-samples/function-sample-pof/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample-pof/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-pof/pom.xml b/spring-cloud-function-samples/function-sample-pof/pom.xml deleted file mode 100644 index 6ac64b4bd..000000000 --- a/spring-cloud-function-samples/function-sample-pof/pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - 4.0.0 - - io.spring.sample - function-sample-pof - 0.0.1-SNAPSHOT - jar - function-sample-pof - Spring Cloud Function Web Support - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 3.1.2.RELEASE - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-starter-function-web - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - org.springframework.boot.experimental - spring-boot-thin-layout - 1.0.27.RELEASE - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Application.java b/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Application.java deleted file mode 100644 index f645883c5..000000000 --- a/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Application.java +++ /dev/null @@ -1,31 +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 functions; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -// @checkstyle:off -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} -// @checkstyle:on diff --git a/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Greeter.java b/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Greeter.java deleted file mode 100644 index 2f1eed816..000000000 --- a/spring-cloud-function-samples/function-sample-pof/src/main/java/functions/Greeter.java +++ /dev/null @@ -1,29 +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 functions; - -import java.util.function.Function; - -// @checkstyle:off -public class Greeter implements Function { - - public String apply(String name) { - return "Hello " + name; - } - -} -// @checkstyle:on diff --git a/spring-cloud-function-samples/function-sample-pojo/.jdk8 b/spring-cloud-function-samples/function-sample-pojo/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-pojo/build.gradle b/spring-cloud-function-samples/function-sample-pojo/build.gradle deleted file mode 100644 index d033c4a27..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.0.3.RELEASE' - wrapperVersion = '1.0.13.RELEASE' - } - repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } - } - dependencies { - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'spring-boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/plugins-snapshot" } - maven { url "https://repo.spring.io/plugins-milestone" } -} - -ext { - springCloudFunctionVersion = "2.0.0.BUILD-SNAPSHOT" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile('org.springframework.cloud:spring-cloud-starter-function-web') - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample-pojo/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-pojo/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample-pojo/gradlew.bat b/spring-cloud-function-samples/function-sample-pojo/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-pojo/pom.xml b/spring-cloud-function-samples/function-sample-pojo/pom.xml deleted file mode 100644 index aca6a77fc..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/pom.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-pojo - 0.0.1-SNAPSHOT - jar - function-sample-pojo - Spring Cloud Function Web Support - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.cloud - spring-cloud-starter-function-webflux - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-surefire-plugin - - - **/*Tests.java - **/*Test.java - - - **/Abstract*.java - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/LowercaseConfiguration.java b/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/LowercaseConfiguration.java deleted file mode 100644 index 45afa2e5c..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/LowercaseConfiguration.java +++ /dev/null @@ -1,38 +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 com.example; - -import java.util.function.Function; - -import reactor.core.publisher.Flux; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Dave Syer - * - */ -@Configuration(proxyBeanMethods = false) -public class LowercaseConfiguration { - - @Bean - public Function, Flux> lowercase() { - return flux -> flux.log().map(value -> new Bar(value.lowercase())); - } - -} diff --git a/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/SampleApplication.java b/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/SampleApplication.java deleted file mode 100644 index 52fe3dbf5..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/src/main/java/com/example/SampleApplication.java +++ /dev/null @@ -1,110 +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 com.example; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.util.MultiValueMap; - -// @checkstyle:off -@SpringBootApplication(proxyBeanMethods = false) -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - - @Bean - public Function uppercase() { - return value -> new Bar(value.uppercase()); - } - - @Bean - public Function, Map> sum() { - return multiValueMap -> { - Map result = new HashMap<>(); - multiValueMap.forEach((s, strings) -> result.put(s, - strings.stream().mapToInt(Integer::parseInt).sum())); - return result; - }; - } - - @Bean - public Supplier> words() { - return () -> Flux.fromArray(new Foo[] {new Foo("foo"), new Foo("bar")}).log(); - } - -} -// @checkstyle:on - -class Foo { - - private String value; - - Foo() { - } - - Foo(String value) { - this.value = value; - } - - public String lowercase() { - return this.value.toLowerCase(); - } - - public String uppercase() { - return this.value.toUpperCase(); - } - - public String getValue() { - return this.value; - } - - public void setValue(String value) { - this.value = value; - } - -} - -class Bar { - - private String value; - - Bar() { - } - - 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-samples/function-sample-pojo/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-pojo/src/main/resources/application.properties deleted file mode 100644 index b5dc321cf..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.cloud.stream.bindings.input.destination:foos -spring.cloud.stream.bindings.output.destination:bars -spring.cloud.function.stream.processor.name:uppercase -management.security.enabled:false diff --git a/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationMvcTests.java b/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationMvcTests.java deleted file mode 100644 index 15c366478..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationMvcTests.java +++ /dev/null @@ -1,51 +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 com.example; - -import java.net.URI; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class SampleApplicationMvcTests { - - @Autowired - private TestRestTemplate rest; - - @Test - public void words() throws Exception { - ResponseEntity result = this.rest - .exchange(RequestEntity.get(new URI("/words")) - .accept(MediaType.APPLICATION_JSON).build(), String.class); - assertThat(result.getBody()) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - -} diff --git a/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationTests.java b/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationTests.java deleted file mode 100644 index c70be8011..000000000 --- a/spring-cloud-function-samples/function-sample-pojo/src/test/java/com/example/SampleApplicationTests.java +++ /dev/null @@ -1,122 +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 com.example; - -import java.net.URI; -import java.util.Arrays; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.util.LinkedMultiValueMap; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -public class SampleApplicationTests { - - private HttpHeaders headers; - - @LocalServerPort - private int port; - - private TestRestTemplate rest = new TestRestTemplate(); - - @BeforeEach - public void before() { - this.headers = new HttpHeaders(); - this.headers.setContentType(MediaType.APPLICATION_JSON); - } - - @Test - public void words() { - assertThat(this.rest - .getForObject("http://localhost:" + this.port + "/words", String.class)) - .isEqualTo("[{\"value\":\"foo\"},{\"value\":\"bar\"}]"); - } - - @Test - public void uppercase() { - assertThat(this.rest.postForObject("http://localhost:" + this.port + "/uppercase", - new HttpEntity<>("[{\"value\":\"foo\"}]", this.headers), String.class)) - .isEqualTo("[{\"value\":\"FOO\"}]"); - } - - @Test - public void composite() { - assertThat(this.rest - .getForObject("http://localhost:" + this.port + "/words,uppercase", - String.class)).isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); - } - - @Test - public void single() { - assertThat(this.rest.postForObject("http://localhost:" + this.port + "/uppercase", - new HttpEntity<>("{\"value\":\"foo\"}", this.headers), String.class)) - .isEqualTo("{\"value\":\"FOO\"}"); - } - - @Test - public void lowercase() { - assertThat(this.rest.postForObject("http://localhost:" + this.port + "/lowercase", - new HttpEntity<>("[{\"value\":\"Foo\"}]", this.headers), String.class)) - .isEqualTo("[{\"value\":\"foo\"}]"); - } - - @Test - public void sum() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("http://localhost:" + this.port + "/sum")) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - - @Test - public void multipart() throws Exception { - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - - map.put("A", Arrays.asList("1", "2", "3")); - map.put("B", Arrays.asList("5", "6")); - - assertThat(this.rest.exchange( - RequestEntity.post(new URI("http://localhost:" + this.port + "/sum")) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.MULTIPART_FORM_DATA).body(map), - String.class).getBody()).isEqualTo("{\"A\":6,\"B\":11}"); - } - -} diff --git a/spring-cloud-function-samples/function-sample-spring-integration/.gitignore b/spring-cloud-function-samples/function-sample-spring-integration/.gitignore deleted file mode 100644 index 9243c63d7..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -.gradle -/build/ -!gradle/wrapper/gradle-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr -/out/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-spring-integration/build.gradle b/spring-cloud-function-samples/function-sample-spring-integration/build.gradle deleted file mode 100644 index 2138d4667..000000000 --- a/spring-cloud-function-samples/function-sample-spring-integration/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.1.2.RELEASE' - } - repositories { - mavenCentral() - maven { url 'https://repo.spring.io/libs-milestone' } - } - dependencies { - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} - -apply plugin: 'java' -apply plugin: 'eclipse' -apply plugin: 'org.springframework.boot' -apply plugin: 'io.spring.dependency-management' - -group = 'io.spring.sample' -version = '0.0.1-SNAPSHOT' -sourceCompatibility = 1.8 - -repositories { - mavenCentral() - maven { url "https://repo.spring.io/milestone" } -} - - -ext { - springCloudFunctionVersion = '2.1.0.BUILD-SNAPSHOT' -} - -dependencies { - implementation('org.springframework.boot:spring-boot-starter-integration') - implementation('org.springframework.cloud:spring-cloud-starter-function-webflux') - testImplementation('org.springframework.boot:spring-boot-starter-test') -} - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} diff --git a/spring-cloud-function-samples/function-sample-spring-integration/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-spring-integration/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 1ce6e58f1ce8ae3a3be37719a2180b5567cea91d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54711 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

{EUh!tI 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 diff --git a/spring-cloud-function-samples/function-sample-cloudevent/mvnw b/spring-cloud-function-samples/function-sample-cloudevent/mvnw deleted file mode 100755 index a16b5431b..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-function-samples/function-sample-cloudevent/mvnw.cmd b/spring-cloud-function-samples/function-sample-cloudevent/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-function-samples/function-sample-cloudevent/pom.xml b/spring-cloud-function-samples/function-sample-cloudevent/pom.xml deleted file mode 100644 index 6b9360838..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/pom.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - 4.0.0 - io.spring.sample - function-sample-cloudevent - 0.0.1-SNAPSHOT - function-sample-cloudevent - Demo project for Spring Boot - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - 4.1.0-SNAPSHOT - 1.0.27.RELEASE - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - maven-surefire-plugin - - - **/*Tests.java - **/*Test.java - - - **/Abstract*.java - - - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - - - diff --git a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java b/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java deleted file mode 100644 index 3e59c45ef..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.spring.cloudevent; - -import java.net.URI; -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.cloudevent.CloudEventHeaderEnricher; -import org.springframework.cloud.function.cloudevent.CloudEventMessageBuilder; -import org.springframework.cloud.function.cloudevent.CloudEventMessageUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -@SpringBootApplication -public class DemoApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(DemoApplication.class, args); - } - - @Bean - public Function hire() { - return person -> { - Employee employee = new Employee(person); - return employee; - }; - } - - // uncomment while keeping the above POJO function -// @Bean -// public CloudEventHeaderEnricher cloudEventEnricher() { -// return messageBuilder -> messageBuilder.setSource("http://spring.io/cloudevent") -// .setType("sample").setId("987654"); -// } - - // uncomment while commenting the previous two beans -// @Bean -// public Function, Message> hire() { -// return message -> { -// Person person = message.getPayload(); -// Employee employee = new Employee(person); -// return CloudEventMessageBuilder.withData(employee).setId("123456") -// .setSource(URI.create("https://spring.cloudevenets.sample")).build(); -// }; -// } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Employee.java b/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Employee.java deleted file mode 100644 index e1f04615e..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Employee.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.spring.cloudevent; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Random; - -public class Employee { - - private Person person; - - private int id; - - public Employee() { - - } - - public Employee(Person person) { - this.person = person; - this.id = new Random().nextInt(1000); - } - - public Person getPerson() { - return person; - } - - public void setPerson(Person person) { - this.person = person; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getMessage() { - return "Employee " + id + " was hired on " + new SimpleDateFormat("dd-MM-yyyy").format(new Date()); - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Person.java b/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Person.java deleted file mode 100644 index 99ded7514..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/Person.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.spring.cloudevent; - -public class Person { - - private String firstName; - - private String lastName; - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } -} diff --git a/spring-cloud-function-samples/function-sample-cloudevent/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-cloudevent/src/main/resources/application.properties deleted file mode 100644 index 2d0521080..000000000 --- a/spring-cloud-function-samples/function-sample-cloudevent/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -#spring.cloud.function.definition=asPOJOMessage diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/.jdk8 b/spring-cloud-function-samples/function-sample-functional-aws-routing/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/README.adoc b/spring-cloud-function-samples/function-sample-functional-aws-routing/README.adoc deleted file mode 100644 index fc0c41a2c..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/README.adoc +++ /dev/null @@ -1,7 +0,0 @@ -This example demonstrates routing capabilities of spring-cloud-function when deployed as AWS Lambdas. -It is almost identical to the `function-sample-aws-routing` , so most of what's described it its README applies to this example as well. - -The main difference though is that this example uses functional bean definition feature of Spring. - -It also uses `MessageRoutingCallback` in place of `spring_cloud_function_definition` and/or `spring_cloud_function_routingExpression`, effectively giving you more flexibility with your routing decisions. - diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/build.gradle b/spring-cloud-function-samples/function-sample-functional-aws-routing/build.gradle deleted file mode 100644 index a641c315f..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/build.gradle +++ /dev/null @@ -1,93 +0,0 @@ -buildscript { - ext { - springBootVersion = '2.2.0.BUILD-SNAPSHOT' - wrapperVersion = '1.0.17.RELEASE' - shadowVersion = '5.1.0' - } - repositories { - mavenLocal() - jcenter() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } - } - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:${shadowVersion}" - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - classpath("io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'org.springframework.boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' -apply plugin: 'io.spring.dependency-management' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "3.0.0.BUILD-SNAPSHOT" - awsLambdaEventsVersion = "2.0.2" - awsLambdaCoreVersion = "1.1.0" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -assemble.dependsOn = [shadowJar, thinJar] - -jar { - manifest { - attributes 'Main-Class': 'example.Config' - } -} - -import com.github.jengelman.gradle.plugins.shadow.transformers.* - -shadowJar { - classifier = 'aws' - dependencies { - exclude( - dependency("org.springframework.cloud:spring-cloud-function-web:${springCloudFunctionVersion}")) - } - // Required for Spring - mergeServiceFiles() - append 'META-INF/spring.handlers' - append 'META-INF/spring.schemas' - append 'META-INF/spring.tooling' - transform(PropertiesFileTransformer) { - paths = ['META-INF/spring.factories'] - mergeStrategy = "append" - } -} - -configurations { - testCompile.extendsFrom(compileOnly) -} - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile("org.springframework.cloud:spring-cloud-function-adapter-aws") - compile("org.springframework.cloud:spring-cloud-starter-function-webflux") - compile("org.springframework.boot:spring-boot-configuration-processor") - compileOnly("com.amazonaws:aws-lambda-java-events:${awsLambdaEventsVersion}") - compileOnly("com.amazonaws:aws-lambda-java-core:${awsLambdaCoreVersion}") - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-functional-aws-routing/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM z5b&uBBCA_wdL?^xw19P_F!l$XIUCIG0(Uznb36A^l7CS!0R}%?tUXwj0HwXsK4>8v zWE@fGYQ(q1F-!wr2v#*y7wWza-i5khqjQYc`6WHxhz85!iY%{Wb*z~zziBKpL+~P= z5yWtFJwj0m!TPZcI??gVUnnQOG_s*FMi>bxB)n3@mOYG~$F8 zl_Xm}#nH#t1z6WP61iq!0zB{Jh{o+KuI9xVM*x|TC7COi#tnUn_I;MA4`P!sk}}W2 z$gGS}m_|3n{2>Nib`R}0pU=AR9)Uh6;G*?1T2ZSB5`4PjrO>Bt2=i6u=qr=bN)Jho zMV?Wtn1yFbC*Io^`FFE6o|ePN6GG{zD$mtIc0OSsefFkNdF;nI-VNeuPS?6%IPVoN zZsFOKggP&tnTdglp;!r1nb~ME!H<>dW?N62A>Q1QI7WDZr;ehh?{L3L=pIMlpL9<- zCZ-fg1i?An;l=twL*C@`7quCoH<3MF6KapUt`yRJpF@_5T*SKkjpGkuc&h|H=`ud? z`ZbMU&m4ld%TU}+A+8V~1;8C{f84t#jj{05Rv(nfKmS(5<=Ac8!Twv+zNQ2KAo$N0 ztE8Q?i=mCpKTj(+=3sG#PuZ69xtt)EQ_E$H(y>G9(Tc1>K{$_6M z*(L~w^!?vvr`|bde{$}8^!2_!m&7A22>lTX_-4~b$zzFP^|OM2SO6_YC(5x3nDFZF zLEs;<=Rhe2kWFopSdxKt#+6GlvG$4b&}%<@1KN1(I;X?0JG+# zOZ+SI(Rz6pJnLxoojp_o=1!h~JgSvFTm#aA(MK;!EfdNVDQXa* z&OSYBpIIn<0tfRSotyL5B*mozW{+MLZ6NMLdlU~=0cuYk{B}v^W)@XIJ)rGX--$xE zOcvV!YR_%}tq!75cM%KJ4z>o<-#?T-I%Kk_LSFz{9lHk$0c_9Q_`|<#-aCblZ)o=E z*hH(RzI&AO5E03$9B2e^8%VO=Ic`s>OC%|BVCLoQQbv;^DMQ^Uw~-6%GO^F}H0Q~q z^f33U->p7+w08Mu`8u@@tTTdOW34aQ*zLPo3M*ZgM$1;R*;#AtJ6(i#%35VYXVR~_ zpR*$Hu4*h>k<4nGL6_ctd(c>3Fj`0BNeVt%XZj?1n3pFSWG&#xyR5p9Jv$6nTu7ep z?1&YWZQu<{`E%?dM-RU+EZMY2%EDea9xT>s>$*;qAlk-5oOIejvmMX=Dq4!!RUk=a zamTctj!;C0!kjqf;w{^1TIo=<;5h(Fc&cSFE^CdtNLq|vxH@9x>|8h1&ggl0X!ym_ zxDkU%TWQgqxL#tcz=HsPkx1(`m~!V*zIMr!EW@nJ8EsF5D1i?_3bVt6HC-~|(pC+o zolB0hY3Npl)MYwqOg)KHp8bH;7}-IT!ab|vHd#`jh;fZ<<}KC7PEI6)jPuAiRJGC5 z2&o+9RNmrt5uHY7Ei0NyCNA<4mLnKiFYNv_Zb#Nii3WTZ0arZ8AT4M0>{%QkfFKHD z$$+eh87@<>*<{1qeS%#EY7=9pnWpm2e2)YsTnSN=OZ;bh@jzvAJ7{9b^qHwKQXd&- z%P@H^nn=iub17MjB9)=GFUvK6%wfa84NFp5%?$!9s);AdXonKo1(r8TF-+CxrZNsr z&~Nv31)}ejFF>%}r3{F{mBb*6PpWF=m1;g?!&1Yw@g9xX(CztT)5@3!PJ$MraL?jJ zjIfepZ3R}0DTSdM7v5{g4CqqENzH&qX~|~OOAZ?k(03=3VqR=omosOJO0#<^kry}S zMOVziT*;@o#igZ%dH=|V33S4P3X#diBc9o-J2t^IYq9m{K7GEtHmM_yBtV6$dz7+GSDI~g-K~b{o`Ud#% za0>r2$Osa6KCfwq^?pc*f*-YeG33x$$Cz>r@k4A{>e&zlHn~AYPNFAkSGe@|SF%2qflcY{3Q}TP1xU;;lixI`{PI_{1MwPU# zb8@!|+^PX>d@Px~2o3tYZS<^mg8`s&^A%j$#_ecM)T0-=M6*JcsBjG$6!qH-)6k^r z=hP|(rciXq{A45YWNjc*3tE28s-&}Y*eX(?Dl3}SRu~$6>Iiz?;9=wGO3&_yuud9e zI;ydoyIqTk1TB7ZTT{o1+!@^A%5#rZX4&G?bC6Vjp}Q)V%s16{j$h#-0dMi5>oaC* zU7@wAR|uZ!g;*b6%$SP9WYJtzOSYZDh1c(z!EV*QKzo%BvfbkQv*RPPRQm&M)gPX{ zsGE;rsTtrJ$#Y-96Z*&W0@1o8i1XD}SJet-l%J+a?+-Q*x7&~$2T(*W!GkT;zTp0% zNA(Z6)VBxSak^X6;6eB5FV>%~$+vsI)VmXV3FrLDw`e5ziZ6n180=s3hq09zred)+ zgJxaVKHB88?P~L<=_F^?2OWvaMvl_Lf>sx1GE2t38EFH4*y%WGwX9|A`ZH11xDv-% z3(>w@i{-S_vscw(nT*5!zMm)OY9HA?0x+)$lY58XGTd?$B3bT8G>2Nx$&v++LtnP3 zw}ctz1peYD;s&U(-^Myl#2TRgMq>XF?%dT=NcS~K*x?!t!7>qNE z#XC*r*1Tmas=7$c($69)&0Q|gv4u14v;$|>JCPh{TE18`JLEk$4XUNT)N=8{H?x*& zvob>*k&1|Mkkd%B@&YU_Lcn6yuNS9U<3xC>F0xW3NJsSKU{z_OEIUWa!kVhos3p^e znKBiVqZGn&Zfiz_FCObw-B89YT-{>XtOQQPL1W`9eIoGH-yu`;QO593{jOJqGn?rW z=RZk&t9S(Xl|LZ(OCOgW*&y;4vV)EVx-q4}3kS|HZRW|V9K(LmDf^v;cNIA<6Xu;r zr&oQ^+#ynltMZM`QGV&B_LCdX;Ne^G^-p>$C`a&0*)GRI%e-E{tr+g{@f;iM4wUfPv7pnd_ccS(@ z4{d>u?2E(%@tJmuYw(j8bKAF*cbJo=l*&?B*~c9JD0L7D9LGrhr;Cdt zncS<5VKKJXK?NvGezTQjVUEao!!?}QQz%e#pJ`pN*=dEnReH3bA86g#Q&aLzn9ReZ zzJ$1Y2xzkQdOGVMvC7*9JIRk=IPkJQ2Q3hL%S@dl8N9sAYwsaPHJ_V#Ur9yFWa?cX zjz$+PT{j#E`o?A)2J@8F_`LjHqe`B}I=iKBH6G%zkONe{6sF|Z1v_YQ5&iJov>WGX zipwqW?lIMTBKC>nGA2tsNMx`5CdJY5t}Sz&K$ILDLDC^Pxs_SN&B&jwR}-G3CYZ?b zgKQIgD&Y5pU|OO#CgM zDGuh11j==SAiOZK7m6XE5XW7K(-=sL% zH&+Fz#zLnR(xemV8{F6vc-V`jR7;uVCP}E6Ih=qbmD+TbZ0%-$&Jvj$24?|h9`H!y zP_Tq~oX$EP6%+(9dat$vf8(7vrhU`tFbifgmbiJH(c??;^VknrH z0hsB`p0zIK60yzL%uq8HIxikY-MQKue-X0Bb=6c(wEk*{u0TF8t-_|Q3?O!7wDN;z z>J}_l#!p35Wa#!8&${i&4N1dhNxC7AoA!|VwT*p2*5ZBdic8_~ zkfY8g0D2OPVnL0=o~egN@WK#FU(X>U<#}TGn5vFj1{rPxmoMy%^)Wv?A{ASoTusuuqHD7a5BYf}yH8T5&ox(ckKBEO7Rd?Y?Lp&5oNE!c_F zq_zlC1$F{`-KoyC!}LT)RKJ8?u*ioiyHCbjkW@hWoNawAxb?(^dk1pHOkmE}1>J0> zG}DEB*XNnF=GEwAtr6@@RUF?=NFRWh9Yu~`=$C7-iLKM&68Z7$lSa2Q*@8# zr=^)HLw~**-4mMU9p_K_q(NUfgw!mT!&mU6UzRR3?O6+Kf?Bml+DG)4;NHTg#V->s zyl2!8bbaR#xq4a%wC5$AyIvN$3K^|=d2<_Bszp}&D?5ICjvp_Di}EDG=9VygTzAmMB#^O zss~=SJf03Zqu>_Z_sevE`Gw-k0H0vQK&)s_8m#@KSCn1IhS-8236Qy3u!>h&Myz`1Kd8B~HlYtAU=gA11kqTr1`MN9eyqp7elU7>IHRBL9eHY4UWJ;U)t{yN*Rm)~+ss$M3* zIi`3)<{@3Z1heF9@JR!C+xWC##A~Hh6;Jo%oqCK$fPG6;Q%&iwSVez+S&H&4Q3Lap zUzp_C?Bd3k@N0J(XK%I*Y8R~CI>_d(Na+h|_@M&n3!V+t$ONDV-MniLcA-)o=n`-A z<8ttu7TbY&f9C8tiFVKgy;}5p4$ktRr@!JYKa+g+S!26-yZ6r1b6BM82c`o(|AP?0 zWsdI&53A&;EqYJ|$mNdP4zuWK+h<-`H>2EvRYzSDeze~owhCzF^0Iu^xV^Sv!nqE-4@O&@C z!xw^61W&#Ioa2BSBx>;v{M8g!r2;OpS_^Wo%k?M z1ce90s~<)S-q0se_|)Ik!#!_j=fCxaOQcL`BqD`8@WsGWMqEx#v)r zTb_n1GZNvTYT}r9Ag$(i!8X6 zNU$YbD2sh6*}S%!#>qseXVzSBf>J|g&tP1*6;F(7o@z5yBV>-A-B7jDD$%}mKu=Sk zf%YTL_D!P3ujNo-A&!SXL@>`t8oeE<)7Iexa;)be(pOWnJo`y_%5?g?Bb{Z}ptE2I}2DbF^CCr)96 zZd?xW*TqH)B}#ln^QHMl0vFi9DB#20TVb)V^Qgcn0)Pn5QtC|S*aXu1d0YZVxclWn zla0V*_UL8ZB}?}GpxUEvE}5UU{g&yp2-u3POD?+vzbH_ZIN zRg;d~&1^c-`zGviyarVb*dbjO!waqeW4;Cq;S+k3wYM35$?xwUuWHYeBT!~ui^?u2 zDTZnl*=D}kWhrQysw44&$Nj-HI2T1J7ejOO7yPtWc&(=}{Xst2-Xpm5Hw^?R(nORl zSOwG`MxuD_>usNDbhm*wP?Gs$a<)_xk^J>MS8yA#9>Iynllll{WARg{G;EHXW5~Rm zL-|Z^83y%jy-5Zok}|{6-5&6+f3dejs1#g2J()gyET`p4#!=Gv&R=kKKGLVG{l$(k zuBnqP2gKL?<)D89(n(*PI=2Aj@{|2D7901rk8$xu|E<3{jctG{$?BJZ`OP_jqll%=o>SRg|iFp>7h4N6Qe#g*&gbN`CDKxlneuB#GKMN82a|&*-r|8(MUx|XCNs?v_@JrwJ}g0 z1b>lmV2^)q7zrPHc~=+}f7ci!e^K~w(iTHcLQ(?qQO+vdSOVfHybl9#9F<`NjAfiL zpzfSzYhGQp%_aHC$W(cOU0HnZBS5*)rKKjoVXk#yv8|-c70uVW{NZaZa+h72-E7fR zVcaym*Yi3l2bwmQgK^|i|uC9JmO6AKTOo5vSaE7!I z7ZHBuWomktl`=e+6bx-^L31&#i>t|oUVeMQkI}O>)vi3Otn+MRh-9msb!l8`zjS>e zMnz@@b3)gQ)5J>%)w9Zk?$$!iRb}du99&z~D;Ki_0S#o?vL)fjY*wm?^GxM${*Gun zIEbK*(gVC5#6>583s9<3>=)c3k{hbUdh)$UU|bAPFuY&}(krSDl(Zn43%S=hmgshs z=rhpKIIsC!BgObZ!2HuPa&6Q#rAL%7pzPV<=a#n$B&0YL-_V(;Nhr&F=vu37+#xim z{vkE!+&$}q(@;FxP`p?e9ZC z4vpX_#JUbq>_JIgbvIfvrRMIGnav%=hkdOyHPk2j&C_|64`1BE^$=?XOI`Or;6f`i z%+&w0(j-K^MUP-Qc|Xl$J1UgL%$O@>;R1MDR;90qh}(>`OjQIL#PO^Ud7^a} zKEP||e^%jto&@%3V@I!Aq8DlAuW`A;?t{==&x;q%Ah_q{ix0630P2@y;*klP4#WSD zaYvrc6eb!k*X9f+Blw4B+{c_A%nYIP2d0RBGh&eqBaZ_z#;*Yt=}#OjhOqCy=#yQI zhLnTKKJa9b`vB$(Ao&k6%Y3HIpu=gwm5)Ip7dYg$+zm3+8Nuv4&&&(s1N6d8d!kDL zlIe#s9t-S|d?E&24++OCMt$N4hjc`}+dEZx>O6oyo_|611-z}D z72Qwu`{x!>AM|UH_ypY=KYux@1-d~&Lm`*!P$2dQUO7(kmUGD(27|Z}pD-<%rw|?YSLpf58810bgRZon-0n3jtyb004^rTxa-a zKd7jOsj=&SJqSxx_cXv!#rz}NG-1cK6k?auMoCFSYP&ciI<=EVEUAn&zGAbORkS*B z%c8k{9kQ{32LVMvK~;o9gd!qZ+b(zk77BjX0nkOz|t%ZyQwv6Ar9!-%hi0EWRDop&s8J{t(y0 z909e1K0*rT`AAn#<;Vb(bB}h&+k}H;$ou5^)5N2{!G|CKe)3JY>CrILmm~o5W0!tN z9QZxM2S4Fvh-nIpfqDROrU(*+G56EtRg<3&eRzWdV<7qQ+Xp}&Vm}(thcbX3{5}<+k7`Q(^&cHM; zpl;S8UR>zsRN-u#ZSFLxXXd&w^ZzvKkH|Sx|QW;}y zwwjPUwZ>^iUL(>(T;Vp?Oug3rW|qX_4^=p`p$h~p-0jjdiZAZ8#u6qq`J`B(vzM0q zNULLZBad0hD+w7&%@y->WE`Y&H2F)MZLeV;-OxonwCUHW9SFHb;wf~iO&b;(Y@u? z4%$Tw*5v5}98V zAZ>y~BgD&16*=U&=dz6A*+(*dzh4#d=V|EhLBCRaXjJAGzl4-l>$eh+yQQ<~dAmqa zl9#Dzi85)r)=V+bZkEbESsx^rK}j9w%QKNhO3EVOuo4|as4O`0gg{%5M33={#iFwY zV;t7oFqNM>lkPhc4SLqt@NKudj9#nk@;Mm_B2%2BatkFH9*8KcQl|t{KtSjgY z*dyH1Y4R-;uFe>yuk6y09p9}tk*IiQ^&8^Sb@1RwZbDM_s%t=P>0%2-4+(#p&v01E za#7~6OOU}-)7YC^v^1Zg8OOp&zdawbSLKP_iyYi*wnEqBrE)tmr5bIJ9x3%`j7r}x zrGnd+LZ!r@`U&7y(%e?A*VWQee<0^6K6LGn9LX2e#T!d7ldXD>cKA|dyXwhakc>^Y zU|}vjw2zC)R^_3#xlE0`peQcn#`>Y_{xiPi0P;tf?S~YbRn&_m@tTckq9Zo#x#_-- zXdr7e1=gl};Kd#_?fo}C;+H;8`Jv}5%78(8)LH9o3C7p&40<_JO;wcAkjx!LfDGk8DQwau;V^g~l&8@j40GToR?g^-kw zg`U~VD4<;(?gO>o8QOw*o2eOY%b-hogBy+^-P~}9oIk8=OqN)mPV%ErQIVr$u9Zim zPWVp?=}kFPByX$Q9>3O3){Eu(Mmz!xX_{dUCp)ZOqg4dAitL=*7skIWF`qgcKR`=| z73~K%jpmF&%RNio5*}ZrrMQ@dS9P9qEzVREVS!Mjv5?wQ z$NUT#V;GsVUyHZuVn+B#;-QoqrCZjcW86wvJ2!mql*$(h9N|>;flzX+%cPISgz!D)|S2qu8H6sywRqb zH0|YusE-pxerVLq91EJ(4y$S#*5sVlS{7Q1Vm^3dsVzb!C&%owKGo#j+`M5C)`bgSG;KJ7N}V}!HM{-L%%=~hF|}OP z4B=oEPu$ARBWjggMLMW@qnJ2F=a@E5j$x(taAwVba*-i(rC~K~U~CT&AZ^_$pKLC_ zcrJm`yAp)aa#0pU5qG|83u#T|UXiQLGw56RvP9?Plv-;wZG0inQw`1tRbIDlZMG=$ zS|gNO>O<1ZoG2U9Lc!4dAc0qg5MG))j%e(Yjl)iQ)Ae*@?MLAFvMW%2jj zZ2vR`>O-0iRM!3s%B4PpaPN0j&1YI~KjGefFmdX8yi?5`G;JSPJLX19CW%R>L$-2l zg0ubJ)Vj=k4Sqv6*<&4k)JnT|?F343%AoH?&=Y+|^>*VWRx+B?3toG)Nif@!Q1Iad zAo=-XKjdoIpdAq?5jDKyD4h?#;w42Jw}jb;b*m9wl&veNO;Nd&u%acq5R)&6OCxD! zcTzK&>e)#3gsx=jR&3DNKxMOeUipkG=-Fjo@&fs9jJ;EIW!=8+orlHDoo3JJSd@`y+1I$tN#2dj6pE~%ELv|P#LU> zoiF2g3Sa$N)aTgCV{So-dAT@qt|W;9pT34JdcC5%fP$a_bA0s+=%|1Bqa8i?P%GQFXn@ny5sv z$hoFJZ8|eCPH#@tHZK+Tk_}5%!xkj!5;*zf_RumpDb~VeFVHCD+&r(RPP=$s%-meK zfpkJYx{;+d6gVYZPvz&>>KD{MD&A_eUz; z-J>?U)P~OOTL_uhm5ERMn+V;@p2SyC3*99lwtX+3|X>OZn3?WV`e1N zXMW#8K>SF|`4Jx?KQ_Q1E%qsv(Z^0Ie7$A+R*LA{#tw0PH|hO)PDff)ym7Y`Z*&E^ zDZ+Yc_Mo2gbbJf_&bLba=M&AU<83pI@xe zAfIp-=gbZ;@$sWxHKEQuk7E3cXJ^T7d}w9M9Z>>&r;O?BDyV5{s3_nYDCrkn+umNA zOZiEk0Wn2Ny@?YgUS$IccYX#1?rn3#Sd`=nY;)0h7|LD6 z4JU?z?sUhmpzmdYC~N~f`AmT&Mf)%bA!>^fQlb9wjItGcQk(q_d~vMLb==xB60|tB zEF;4Y&$XPOOxnP^N)nQpni)u`BLp{Cu{|h{TG373ctzG70Szai zdfAf((wJP2MV02XykIG=+?}sw7xYe%t{B6UaVTXMqI!xa^+=NHM?&0k*l~#_s6E4Q ze)jCi&R!#Bp-eV%!Th|L=U_jRTp9|PyePmbxDD~5)DLo3j)xuNDrB1@@7j4;1@$KI z^*3w#-=Vm@(fLKcGAtIFAS|eawsoXFid<^@6CwsQmC@&vsL}E_w*8+L5W71w3t^A!F zl?Lt|G9LC=8i4Gwb@DA@+6j_Ik?3s1w|^#r>AzP&-KkbuNJijd=jchdM4=1O>X)08 zKux(&W|)oV8+Rz6@XMlw3dvGNmfk3{DF$t5h*cZ3eq{q4TKgu1J`^u!)RrnAr7jXi zE+v{qGR{^f0gk4a7baDwfg;VSNLGH@$aO{Y&X>RdrQ|@vZEB2Igd-?QyEG`O^kZ8w zy)4Ycu&uY5osWQ{YPMF;Es_aEC@wWyCVHVEufUY#pd8om7#d$T)hG`-V-tnXBFJ*( zn^lHck;P1$k=Wq;AZ(qI6ugCD5*jA_21gs!uFjz*zZM<6srgenF)rCbeo%1*xT?fZ z2vyO1MWI!`SmoTHmLg4U81JUm*YJ%Y@;xzaF~{IC_pSR0M6DLd?BB4>FuvCtXo10OHYn7xB7?}dW9r^o3f0noO8z zF>xgry-GF@6OL`HwL930GNbNg_h<-BW7jz&8XTs|i)sx%VBH-Q#88$Icy+pX!RTK9 zcxw^A8AC{E;u3X*UM@Xm%5Zh}4W*!o2PTvgPls}qtCt*d^J&#!4AO+hLPy4-JZ;0} z)T!r7-3@^#<{=_gkS+&>QH>fC5Rq5jOx0K0-*8oJmN=xdepoqZA&PgVvptyZc<;W0 zX95C&fYzzwnx0%i22m7!auQA+@Zw=&)|kCx@Jg1AVo43 zIOTE=Td=~Y&Lg0d{(~LNCgF0hE^b-V8o3hgviLq-lg|e#AySvbG7Ir|PvIiGjR{X+ zv?YZl{&p>S#N{aQt$fC97*TabZKq+3|BUl zBFl@DF+;NCYxCAoK=CVxf{-T@@t@oJ~7q;_6QAcfWv6uFimU(pZO(^ zF-0ufSPgBLiQYW+*)U8s`<-|_N|@r9^hVDn@C2FKoQ+7sxSc7#yoFr0U# z{|=&N0M`8FhB)*yhb_{b-T^_m=Syi-sgDEWO zE3~Y^lESRO&!w-e?yzhJP2^EcEXmhm{^vN{o^&=(9mlO_jB{NS8<_S?B+k`|W5b8tCkk`ik! zP~h89#WaF*P$$MsOLBLn(4~TKt}W=VgxtUi9R(u{^I_s56?k)T2=0@3{ANXIJhj$1 zsop=_rnp7pnDsO_%p48jW7TsnZtN62+zodXtB-J_dq?mQYM3?SYMfCnZ&t9ZQ2iD< z%s+p%U9>l>s+z3c{<^B~NU2WnysqvAu(B6BSm2}-)mhB=P@bmuALR|h=r}|(Yk_Ld zuX-YtlQG&CU87jzYOT)lgk64hU*=LzTZYkbSx#1!+t#_VtPf!J*XxIbz7!^VP2&!f z$*=J6Lo)4DABzQsAIElQO5W@6#@P3G({;4-Pa$L6xcRq3uFsoqFWi7jS^IF~k-0Lu zxVf?^CFn-|oMv@(tH~H%C1qN^JXBO)Si|rLX%Faj^15i~>OA2)9`zw>p6#0-vw38w z%^KUDx&}Vh7|lSweto0PKO&?3qAF9EBr}9l>_qB=Tbxp(zu3ZPNJ$)AB=eC5uVL^5cMRB{MgKHK|1?ka5N82HCX*|`5o0^Kr*!6s(rJl$ zUi9}JvbAXx_uNlBK;!3`uKyRw>7UW_|3ai?sav_>E};Wga5TetCGoy|Q49fRB%)cB zf`|DgC-jxaUyzAdZf{stdw8BGh9z53oRlIDDYvtqbQZKI)r}C@TpCxalCuyY##ms z9Br^GU+*Occnm#%zBrDsIt_h!DmCg5lM{?WO}oZmK1#GmU=Uf>J0>3pfW??`@d;jn zQ+MxF&^~MjP;FocZ4pzt5>BK;j9D=SU_v)HS4;U`<7O~6pjxceCb_})9L$|h4?(&( zeC{8N-OG%~Kd~r-7HX~cdB>EC*?_3#-Eqh7hzH)|UkJf;3=op9PI;r0b!x>)zA z;p5gSir0i{+gC)(u2$}|Z&nu|G0ds^P~tNfwe%-N1+A&pUu2%1K6B~K-NJQ_d;V$_ zcb1uGMXEV<$G1CiS02>P_rkrV4Dx~n9G^cImHGw$V9}~FbZ(d9eJ2labLk9G=H42C zLU~ggxxVqjC)`8g{u8=@;$65e|Lg=#c%F(PU~+M6z^K1o%pfO$OTPFkdI5+%DQ2%W zLcxjI_rv)O{Wz@+Y+6_?kEr=uFZXuQZppLE$nmq#$oAl&KW)1a6+wb*6q|}hgE0z> zqwhGL1zL5tJzl_+XYpE6b!@0lDs7aK-ddFRex=`|#E@Oi?NT-ES?$rLr>qLlj234~2cbg)dCFsEaUxhCoE zww0TaG%V5#wg_G`j+??MojaIy<4@DgatbDG@`VVOOyd4xC4jX{iP@I_$JlVdg=)*2 z(wel+EVi;yhs+uJ)R}`lfn&}0E!WdnC@b9hYfv8jKcP`aN9|S#2ut9dNuaAKa=6ZAS4Z`GuXW zT8W2UBIBT)zI;ivj1_UmSc%Dey)IGhVLhSUhYTD3Sk_cC$;-$9Ev5Te;LeN%zbX0{nOfuo7z*QMb^k3f#%fd`zl&1JA5gzOCnxado&-u%_+4DYBck!@s#A< zk+9k$Z`H@otY;3_U7CjqPDmA~Z6qs)ly>|;OVFp%{n65d)dIb~SkElpuf-SpHMw6e zfRe=kPA9%ALxxC(v9t~*XxUb!Lq#RoT>@WK&Pvx^JwpqFPCo-A0CN7ZYHQ37Hcvz> zEbopS-zUWaMV8I(1m7npodZ2Z^lX5#$)>j_3`s}@$kC<(LFp>tphVF-2BKU@1qTUrnmoVYOjUiM)UZ^ozdL6Q8~hHW%PC5LhQ zBs_;iO|!EG^~HCyoJRKM&WNq_0+}5r?P?I8Zapm0&tmRc8s87)<#tP-$ZJZ(a@d1V zrTi`?sO#+ER&s94`aX7NxxV=uEvpK(0D_lnSq}^(YQNYr>R8_F_`!a@RU|5gP0jRU zlO>{4Qc=(jk!(>lSwNA8v0Hi5I3235_G;YA2U$n9lFR+kRXFd6HXAm@kA^(kvGZ@4 z$ZPDaAfmj`$ohP}c&48ls=w+4-QE0RE{3%vMb^UvI6CT+zQU?DjNh@cSKjCB-U=vx zH|Mqg4CH<{#JV(T!4M|g+Tr^ok zq9qm#qcJfxqQ!U#jEYP)A}z3OBrq_kM8B8yo)I~w%=|<8WUZ*(zvHPdBjN5%vDyX0 z-v)NE6UL{$M)!O^9^(HI0JZrqBhC!68-dhYu_v9*z0&A$uGwbqSy6J*~BQg z7L03dlL1HDWS`Pr^}s=9I3E^bL^ZP)jG8|PDdLFKa3+wNpkLg?TV{Afm399sb^47Y zI?}$f;mZOnf#RpzrpB71eCy#YID~miHph#Te>sBYtvRHA(;8Vr{hS^?_3R0#EYnRFnTZ;&44bWTgAcK-dcy~?t$qUrAwTw<7ryWu7g=J$OS(UT zN+cMOR%{Ss>N3KF2ZMk6HQI{yqNOU+paXkg_vATjx0A;%)t0=hBbhGG;bZXtU-|dm zEop(9oct!8V7R0PpJiHfMaI=9X%ZKKL<*)ttaxPjQ5HXJ1o5)KT)QDie_5&oL2HfE zcJ1_MV^vB0aBqIq@ri@}rZ!&u?4XAl=cL9_P`ADWbPVBA%qf^APzGsGm&d5MjZUY@ zX1EsL)!D&nc(T>&Tck+M{=Syeid4Jlw`cJxG$2QmnT!!h52Mv8)WcdOW^B@8150}r z%6)i0m)C>n4n;%AyjiCj`lf%!$JL<~ruSEf}2q{)TvJDv4E8I!H5|tKJ8d zN;J!19IOdr1O^#R`6BCqyzAlhDiLB6PTOJHHQUOiq}(f>Y*t6ZxwzY}FjEt@M#WaE z#n~pj9y}fWH=Jy^_t6GOB~hp+lW*3(wsQXGJiPs}lW+Zr#Qk>TYie2|9F~W{ib_ZH zT1|J=LCuc52_76NZfTyvKXP3JoCe)jR@})ZWJsw34iSF<&Z|t`Q#Gpy$T`Qn)!d>^ z4=Kqiqg!)iu;|QqpuuMX(#RB@(l-hbnL(mj}F2LsgwwtRm$e z;>p;v3>W6B5e^6~`+PV6rhEexRyU)}uq-#Aj-Q-@FgU}0363wojO?NfvC8((hnsq< zx7;u`!puGdHiIQ+L;!#+bAd4m2AjcxGY0P9*ilZL_j{BI8~b2ky3mqzf1l`FC+$8u zLduO30@ck)Ij49|NI>Kd^Jg;OqTLmD)nOBao<2L1H@N}yH@yKu5k|sZ!nEI!JKY!0ajCD+xk}j#bA0onRWj}^<*xn%QMxQG_tvgu+zmapC zKg6h4eVcxj;O%PZNxjz8a+uVpYmTq7NX|(GICWQj-E|AtC(i2yS<|sk8>(yv2o(zU zj*pb5wEJ`jcKg)mHDHVeWeqqLw07+TJk1Ox)A!m*?d9g-@P^#;0PVdw7#QsW7iyy} zt3}0@Ej5xGSXJ#8?waSy(&*hQwxb8{WK0($)xL_g8qK6xsn^ainS4zuEmZbOdqw5h z^|PAVR3;AP;dc*=J6QUSvmK=m+~rYlRaJ4A^KxbtZT6K#lm?6qJ$xh)q!{NROG+pG z?$$=`v=#`^iTiaa?Zo-Fv&gR%I@4!oT{&~hFa=UFA6!fYYJ6g_`hSj(v*D4I6X@;A z)CjUxE?Xrk(^xGf_%1Fn2wlV)nh7@H&E}?C4>Bej2MtO5A-ioUoJ`P4BWCv@d$osVx0k5HbVIb`K9FSZDdmXbO+FU(VmfcVWw?4a^wERqZ z0%yOzT&+d;SdVZzwXMwf`aGc)US&7jxIATx3cGD4=>XEr+~F-M(abJK7bklpZV6oF(x}wL*Q}q_dWDYFXW0)b1?@Z43nRbxCV<&Fg$- z5FIy<)2tZE6Om?vBrl$HSa-Wp^G!321jwK`v-Mob-y^7Wr;;k>gIKXnsB#?`-M`3& z!I{g=T1}w#e~r`sVg)HGwt_g0;@8SXf;o$Ei&<;SI9p%!lFwWk5I~RBMY(V zJ^K}>W3fAQeiny1_x`~z`%$e0qm~Y}6`l;0l4#ux8|VY!oHZ;PsP*omSt;HqZRWlR zB6k-I@<;dK)sTdc2zSs=hM$?m-^~Es)sWOR?&~$VR7V^0=p1sJJ#O6gK+sk+xJO>X z*QYoH#I|RmwP$GM7fJ(8NmE`?TV7$-95N6Fg?(O=8YS1@`V~sA!1@*#00^CUOvMeB zseSBQWczm@0~;qT8Z4+l{ASD_tp%RZi>wTSCY*M*IB}=uewB=4DI^v-<=(w zlT8mztmRo1Du}aho(8}ElpxB677Mry!i(F7DdNaBM|`X!w%I$ri9Q}LyS~Ajp1tjo z5d@{<-SQ-GfkSFb8oAgf76~s7|Cxk{w{wQ4+$YcHvamH|Z2)@I6+u;P2Ot%wirk_6 z0BvLwDHTiI;>XCYOwl96=;V|UqLYe|Of!o32>N0{&3^)D!Zb*I$(R zfAZ_;-2Mqxr27X}-u@GdLvR0o!0XD>Q}R?(lByDtvJ;aNv}2Pq`$~^fGs^a~luC@u zs*H>c%&d*f%xdV2kOq9Uy`STz8JE7=t04 z|CF{%DAr@Y5X%>2lqK!%QIWi(XNl1l)$|!TXi7M zo){E*mvAjx*_@2YqN)4TM3_l9j?ANMA$G{LD--m-NEYvxLk$dEQixD|c;r$l0cO%; z9CuTj9JPCdIdx4+F9Nw98zH#$m$r`0Ns%XF@;3?>C;t|8{OdpXeC_{J7~xa!{iFK8 zzbXqDSzG)^ser$3j~#tT=KZ8?DSy(onEw0if`)%Z#EqPV?QCp5A%Zd%wkDs%OxI70 z{(ptVlT>s+nfYjZU~myM&7n3`+p|cA1RV%v+kV3dxNR2FF`mUe|3-M_WJvKfgba_MxO;Fc&AQY{-4lU+`y=o`gKO z@ICM$@I?XcL%(!1O+t_EO5nAC*YmZo@Kxguz<<)stuPilVX0HqWt;qoV0*>*TMdkDTiha*-sp3LP?b zAOR`-NZW9li*1_jgwtdTTE4~v%WB6Xc8duYAwVL63~#=^IW(YJa^8x5iH~+P>WPkN zC&0i;uXnO<8;S|7>m)G=yOJvSoa<*ZrG+u0o==^}kM?ek*}4(?ic{`vvXFr43w;ar z{BbB}Lh7ph+Hgy(b|INkII#sn*o+=mRl)}KUp7CMB>Q`90Fy2&Ng^=6B~v*i_6QKM z!#Prs0gIjFfJ-uw;E73*r686I2YI;+A%r}Xw*ziLVOOV>8UNRL!@fzzP94t17ms+N z1{Psaw?E`6)Obyc4_2D5G~d1poou5JOHbvoNp|39im|J;g8UYgLvu5ag3`yKX(S){ zq9Gc70hE?Vr!APSQq0c(Ev81=@d6hYgBhBQCPiu{7i9R6~sH#@ZA%TU6(SX zrr+}Kl&!y-BJ&TEnBvbSc=CDuEu{Nb%l)?|s9@mu37!8hUp6>W@UPMpq95i>T5zt1 z?V(n}GYV+nqJ3WnT}$aKKqY_K)ARa=pepOM+wK+8oTKrHPve9nb;I_HcJoOKKO`j2xWK&4P9U~HBfTN9ymDTn-VlD#rFs8tq*4-s z!7u&nc2A!UH1B`!cK`idWi6bXENso>?f+Vt3p$#89@ua;`BxGnNmqVBA8q7ghP}P& z+&Gu0n;A2)i^wR{-=92yfk}?FPd`8%sWOcXs63Cc&Cq!}jQdWcCy`Hj+mEyp!kk?~ z=Y%UgoJ@YnB|r0$wbJ+x5MFK&Iy%#V>Y!q10xQ{41vP4FvY9B=ln4{<5F6ysx(kA| z2-67T!)ii~{l?rSLP`gB;Ny2_pdL%x{t4oM&RTuNQ27*1vEC+A)Ly!3g@Ym$uF%sv zdGz;Ws_}4Q_$Q13p=QGGwh6@brmB=Vf)=ga>Kn_KCEgo_3A^=815>iLxJpQfq*ri( z^Y|XdoYBPP{CCZ|2<2KA*`ng|)MTprb}cUR)+>JEiuH#nZ|Dr^Iw}#k)v~q|ZFB&} zmI~$`QU>h!WOG4lm+#L0k1Ov%WXp68Sk!aO+e>n7Zb%C_L?&V62_5-DO=eCRiaKT> z1NYs4Envw3o!H4#WM>iOVxRZlNI;_zi-XivwN0x$0sSQ|yZsml1zA!d@)#x~fxjIj%rIH1V`Q_i0LLMg z-S_<{yoFY@Tnt{m?~2hge_G^|t}fsVFDgP7yoCutdwQ`3(*|- zIq~rQZ+gH#o4)d=J!Nb5*+1+JKAFw`Rk$TfW#$vvjP}R0-Ne8q@2)_C81Y=Jr*~mw+j+EYB}u`1(rqd(w0R#&WWp|B z$PHMNN(19wbh-BdOX1-@n7Ijh#3*mVD{#;wTkl(yI#!M9eD#)sWjy&fw@(x5ULssc z#6>Gu$jRrwUxwn_gEl`vumO)I11N&ZVfDWl%BQ}s9}$wZv-HMhp3E1>l$S+1 zt-a=Sm`z;W)Gg#SL65?K?3ue{;hpnGxL2HMawPU}KlSkI=)EM`3!0h-`M1VpTO1Un zt#8Fb@jR`<1Qd=HqdW9-6C@#C2Nq@cB-v4+J%uun){c2M_^%}I^o*-#FTYr9^h-43 zDdj?@;uAB}7}?kqcV+8&;}d=*vj8ETVTa4~qwkn_5pNq(;cN(uj9JhKg}xLV@DW8U z5&`wU$j81w{9gy|ubJ(H6yZ+%Q{g;6I!tRD@#FBvz86bS^rg|D%46+KxhDCYi-eQXPn}=G!bT&Gpjc0)|)ThluVM+ z=yU;^n+MsOzky%x{@lJo?!Zr>!mctKY={Cy1ADoS14{S;Ui19q3Cl1QQ9R#O98g?i z0N}yWT&CcvIdHBSL!`x!&S(}zM-%>H!sV@F$A-jNH$gjtDbx=_q9Z8x0ij+g%+Y07 zxTC?a4XI%dXI%P7R4Mt=JHxb+=H_KRI>?PF?!SxS$))(yUY6~day9cMe-)vF7j;jn z^j5dsZoE#cmVHT73^Ec5&b^OON4fBw>X{H3H)?Jbf%ABWGd=u1368Iu^~*VXp=04n zMo{nKJv^GMg5Bj1QSDb5Q^ovidJ!k3kuD2-1+y9O1lyyl<8t~Itu3dP57=mD0M$?r zF_|?mSr(39<*?wo!vAj$`Cnf}0Mq3Bn;HB zaz{Hv_w6xG&?E-~1cUrkD@l(vc0&3RG22L-UkLb)D-+qcZr~;Z$-%Obwg!GNB&B@` z)SG2j^Qwbh_xve^D%82CSDXK9IbZ(c(c_iZ=XE=$iqFi{wIKso8z%7kIO9I+db8W< z_w?1!N4DRW?>t*cbr5dVxn#rzUyV>@u!%JyCGYM$^sM#p^mK~lC9#l5cAf*HFtelqM%$T+vi?Dh0-czyF$9rpC*i}W(F9`IrQ>+&vj!$LyHN{Jw{M1AUTy zCadsJ>96^;%M~g=`PfJPR=7u@K?y-?DZzO*H5O;C@d^ z^UJ#7VOEwcv(#7LDOcwX@(jO_?`<`LJ7=F%0$vealnikU{acm62CT56Ne4Fd6#MX2 zpRbTu#Is79%e0>CE;`bM&&f$XAx#cdY=<~u%lrclr`ALMOoo=W~gYcNZIV{~UEg$aF0*BD6^F2>CeNnTX}J9!KzadQ4kmp+W!BaJXAWmzmGO z;VImJY7~a)7kRBrO~zWZ4t)B;Jh+9b;g(<_o7%1VX$i6#*{`V}eE?ij+b(}oiLiM`GF^xIaP zh$cxnT+WBNek$mL4O0u>nzmnw0Mw~{Trdr=(?)WAPVQp;_po}s5wN}^eJAS~Qmv3n zmSXJ%awpB*#xD%JPpE%#cVaFA1$Kp^uix(!ZEYwRjai(QJT!ww zGyG{hjDm>Z>s9HFcECK{>|}*xjy7b+ifoK~1-#|C8j+Wt@+YBh)}llrKbRjfnnhv6 zdDEHg)eKZ@uedah3aW?HM3l+fg4Mf*#WlWQNK8^6ip9gv!9b*nA&ND&G*YXpSogV5Yzx zd}qFZR%m{Y)<1VPi>4-00Yj5>`)y0)JSo0OZVd>!t1RCe5?&9l)aPwKC-6#KD(u)v^$P!LaC`wg9Zg-Sdx>5z~nU0o?HDF zb$7RZ`MtuBQ#SVyCR*tyU<6W%o3|*}{8=h{a+J!f)14|pAal2e%%;%YA5T&a!{lOA za?wQd#H*@3cSY^y4<7rg7RRp_Yr_0F7aYPz|CwO9LOWj*Zcugf=w4djSFa4yTNE{I z(cYy1(;BN++>8=Mr?Ypz7eh;i+`!y;r&Zn%ZmE%1i2>GpS{t0GIC4T$p@3q+PP#wc zE*LhNu*^rzB)-#wUJ*?K=ZX-nN#G( zvQxf+5P`?FGw~;aN69qAz+_A#zBR(0qCM4`cOA^xMcR${(JNv2d=W#Ey}|BOE43@^ zHN$tzHPiOg+2~j8`wpql8y(4dWc+Zaj`SI^8%3_8G=iBx)sxbQi`)B+rYEVff8zop z3WJNP$Kq^*mAq@i{LS&j2eQtX@C@DuePG@#BMJ=oQi-2hh+VqMHnq8e7kDjPbmGIN z1DM>ZGh0;~v&FNDK3YQzRBEOLQl+Jzp9N`@ugd9G@vP^SRj@56z--J`3KJY99JRKy zcq9~z5-q*qL%haz1QXrR4wK%Q>^1td^)jMd&jv8e>*7K_;gsT8P^4R0s_9mFMjI?e z{EQ+}Ze!oy>WkC656{B!h5h7=x|Gij(?P(fAU-?SY0{v1ERkP>8lP0-xJcip^A;q1 z;5VIO7r)lPnQNMxIMs3DcyIw^VOy0<#!L`|W zQ%2pQrrgDMIh+z=vK|7^T2$*b>i``QW;o|~jADj}&?0yE2HbU)Ic*d3?62EeUF&ik z;e{283NT{q;HY(Vp8|+jOW)hPwQ*Hkw&Ghh$@C4dY-8-wos0eH1p@^wW>oVp<`C2; z#iNFr=3tMjl@l0@es*NFs$(Q^@(ekjU)*qQBnf+im!rY8bc@lR;=N#9&%u~M6vtXLu@~Fw7~zShp5_G z{r{-wF4YO8&viT>-`F<;=I_wRx51&5W603Ec_g7EMMbJ;TEX@DE8mp&PmBTSGKoKK ze&|S`$53PX`hV;Uuk=UZacJAScuW;bUlFZ&9W;8e19j&sh)*|LUed_I|VT!LOhX3N<96LN9k=NMEKN%O^5{6`td^m+$qtxeOq z$`^t9t6rAz5@7Nd$IbWizO9F8(eEjlbcyz;soC2mCtE&xdX7<2k}Z5n99e6*wMNRH z`{8FBTk)}8%vlyK^5I5=^II0Vwi}U5di$h~<6HI4Ookj-y*Fn9thFAlTXyx0d{i=e zsZ<8V*kW2=7ABT6!?kCx)AHZTjJUq;MNxasQA~D*+kR7dASx3QObIuD7pu$NBgZIc z9b$Z%S?FV2LfZgYTp&ue5jTF_WycIRU^W5Hk=zGJ4}bQaV&GG>S5z`DPCEt=!Uj z#*(`$O2o?LO6V2vwl7at z@QRC!_!E(eb?t8&=QxNCW0SJDE^1Dw=y*q5K%%iKKe$%Y9*?T3b|%3<52b@!NOT&J z%ASlb0J6cQv;;*cpgdKkiawC^{TNFOEXzpZH+O{U@O5MmQx08(+}!|Lm=T7h#+%Xf z9;>QH7%!@!wW$MN<=fv@pd_ASTJfL$R~iDy-|I^J&GG){s`FodubQ^gf*SIlM68KA zQB?TBT>>J1qpzD7poxVF&@JC3{0k+8b4BY^#Z}^TG>_(gcfG@PK2#kRAvG%Z7fw3A z4hoySQoIVU`--a>uhmNzCxlIBFJ%Mm+m`@as5+nZSZ&)$&9$8*=1bxdA3e^ z;Z1`dirpv4?7{9~HV5f$-KB>&U^W5NMuKAe(bH#T0kN#aU8IHi?zF?XBlhBy+fjYU zeWCZKTwK!~xj%nl>I4-2v4$O+P;~v^>eG(D?pt9zy zRCBU=@K~i~#-dc{xoLO(_pDV34(N7s?WFn2D_SYeP3ZOdh_?JH40yT}j)%?CrpChb zU`0oWPW@S*$G)Ibi z0o-p_#Y^7jWw=dEjzjvU+Cp|SD$WJDFp$pkZdnZlr?oX~c`~TW76Y|c5OvKZP@DwX z@9OH%5)9Z{z2CaI4YUONO*vX_2B{W*luoTGv<_IM*BiJ0qz#Z4U-%eEkshR~Fg$L$ zZ_o9TA3ck`Dc>Qoo^Qn1&DYX1MuXs~lNQtb8Q2B;7%DDiP7QmtmmT>VmOx*o@Ava} zAvYs=WAD-(QtwH`Wu2IFlV+Z!{0-PggPs8So3a2fp;!2vh)c`|rXN;9+xmnIP1>;Y zSo*uiR&Mw%KMYm+)StEbI7nQ#BdAqFyd8I=lihTbCM)+`e@tp{dl9B(cX&qg!Tx|i zHEegYsGD`^LeeoEt4+?qx$_e0m?=eB&^-$&f(;8`M*0Je~WfkLFTSB_qLr#Un;^imfV0Hb73uErgp`POj|0alOCq z2;6?9j1Mr;FKD$Y=$1vE+J3sv$+SNN+ZwNSl7*#zb=CA8CPVdzy(6~t73U$*VKB)S z8s`<>*i>#55d3z}vdkygSRB_t6Dry2Xb*vpN??c^+&Xw47B>M`c#MUZSFvOcxp)j|3z&$SR; z+F4&$!&qzrgX|iVBh5d$!(2KP9!K_ZJwgl+<24>IL-rA_$2y>yBM=Nt%6)pSA>}N6 zdUDMtMXA)g7bGuQF0TDFt{hI0j&j{0cpgC#zhe+YGGG@wHfo-Vj(k^J2(_NmY|f4y z?+@bh4vx|`r!dCwZ{nqY%i!F7A4?nkS|~JayO4&{OZwY=*oOe3gkg=-M=RkJteO>H zx9zre%h8!))600?Dc=KK5{9C)wfW8x)zB1TgL1jLRIa)gm4Pr}sSZ?C>Sa}FYe*Z{ zEN|>}-#clZO}+gO!+*NHnbtZpC7*6@@qbU={%utM*FNU|!%|FA()}xW%h#aU;3_NI zn7-#0NhL;Qi}vFiiTQW50N6O*XLd=z<*2EeDFxX_K~JH4F#j{yYeBdh`xg{A3s-{a ztd8UC2|l+!Z}0E$JIFu0jcZQ_hKfVtLu>#SWh(QTOvdG2HjphSPvFAcR7tJa4?IHK z_i`d>L#CUDiWycG*ZYN5-D5!pyN_d|8bF6EXdv_EY|Unqk`M<;_O}4aktvN3!BP(f zR6&mT&mw(KZD(uz1?}TJaohvmm6VG|V(?RKhW z>)r?39>@;pkaPt_u;Zn z=`T`(jm${Y`Pw0ZjG0Uy{rX-ce+I548vA_wL_#|j1Al&oZf#_zEo=>yr=mCD8p@x- zq;)c(^%Xja99ruciXiQm;EhtNOHQsTc|)*78aFwyHkkeuM?s71ODWI!%= z2v|m57c?QM(^v2Q8GhBo&XLYV7X#h6)j`eqjB(6R+=6x^k3=wcr|#4-kj+M?7<+U5 zw8e7p7VZ2Iy^ntDt7_g!F6YY@R8m~sXJ{j!(IBsTbj3DT;DqZUEjEOP}W!cw(XdQd{t4{@N0BwKhO zeeYB zVc&2TNFZWt5nZ~pRv(mNw3&)Drj=d8&|xNdkWhjw46#p5 z&?EOXo>8;KZHAKTvolyyERY%)Iq)!jvF1)L!DGm9k^}-I_dXjpje2|}0(^63ov+oY zR&?O}?)PwY71kIDZek>DCOW*=tV#3yX#GP0HBnl1VR<;JzpxB0KQMvNnOW^N)yRsP+0ZKbhI5@cghs85i$Ah~><{GmaoK>F$l<7@@m zkNf-6)!~Os~H2L#;zXe3dEjx@Z#c8XS=1y?F zKFIG3e)}7mPCFz@&LA+z7;#~M`-;CYqK`|S+3bCN262^o!+br+PIQlx3pFEMSs6pr*6=;25LB?-~(_9{L z;s!oQ1Z|C!UI^bwd9sS>Oi4MZvcJ0TAxFFGp2w(1t!OVzh;*ZFN#Q3V9*cpG1QVze zd_!ElcJk+yXeETb@~Vg$vS*N~^w-${i}`B$ibQI6wnDm7F*P?T=998nMq{|rK@F@Zm<3U5fGY`% zXmfVDmWWt{&b<}QH4l+yWm!L#gP*m-_Gr7(NsD9Js2@Y;?lTHE2c|9DFQu#eg|WON zj*MHb48iyGp_&zy*mN5nEq*XsWa2q5ty7=Pi>+&i5e5{Dhl+k;c<4(c-C&PEu#CAu zc8YVr>+DM_C**$?v4OEB7Ktd_2{{P0dNP_TyCE)-isKd|;O3*`C*#>fd_`_I>Teq+ z+2)^CZHq`qhRZ8W97J|DcipI)7)TM`>y52gDKDQecIrjAPxt~ zo^U*Bf?+AH-dGojd#b%dDvFGaVKNKZOEeI}O7KYekg5q097f_!`HbPoT$L!y-GNCd zfuOyJ|V<~p1&NNY+KF+1* zZOG=s*BI+0srNv0PV`44+OjL4SK=?Xw-2P-K%cvVEXvOkF4w{tXAD#_;kASq>DdDs zp{v*fic>86eSyX6%0QB%yzR-Vdk6%P zX#Go#)u;|e$@|xuz^JSIpu&Cp^gzpk%q<`%7Hj$JArr@J{h-k@-wqs#|!ZC8>KY#S1c$RQFW1-Cu({B=)HVxRsi2fV}0A7ruZiglW8%MvYmV={vSa>gxq*v zb!8uQfM6lpZxYLeQD>82Tnlo=Gnfa$JcoRgP$qlv<=F$pCQ1>*oX{rC$$l!w>V-qT zT$qeZBlGYE0z=h;?o3 zrBp6&42|3-X9WWM!c9sqJ4A-BRQKj_ONI85_C_Q3NN1&PmPq4}XTTzm&LaFHaHs;` z1i#;I<-ME<;-nx7eCfU5r{gIx9exFgj$2kb7h?C>;82T7^15Lf7izUOA67+i~zUjk) zP@wYF$hNr9`Dg{tazc^aAcq(`4G8rwb1S@0kE6CkazSzQ1)O zFT8x>g2ZU1TqglAUV;EjFe1OV=}%4geW5O>ZL1H^Bh$CAHMTQ$(Eqb9Ql9)@4zWyb zG;2E1bvLR#A@Ow0d3QPl;SxFmBqjor*U!LG4d%@q5&-(0o@+e`$v1D^u0%0UX|ScB z!H@+LU3W(tcSpG$uXf8VSD!I|dinghETh;ysW*3P9IS#}gGr{vTA{alfSx1=6}wK* zJ8E*6vpTLg7;Me$e#c4iH!gkImhvR4_TZg7i0Kpe6d3S4R2l31>Ni!JHxp-ynWOr2 zpW>J-nq!&PgF7w(k%>3O%FUry6XHHK9lGe69tCI7mU@@cbjtWKO)2t1d`!?XhSiV# zfZ@m0)T`C#N;T@Q4{c~R5yF-UhtiJA6ME+y;1sz|2ooqNRqEszXX}hL97RBNn@f*{|d*bZD zi={%gD9boJ3+=+CHW|j~4=l*wMv3eolu6AJ`Z~z!VCf7kUsf63=wz^USJV~}2P|Kj zFqnx%?#vyB;m*c3@pN5zAJ7tv zIPu7!u_;{rbp-Oyt3fwJ0s`s<#OWgY7rphnu}~G-NnyHHi~5{BHugD5G?4F0BKQH_ z7$5%0fA0pGBMr*Qi(}Ga__UJs4nG-v){Ta7nUjsiwDV-l%DFC7rQU> zn4KP9uBb1%TDmT}n5yr$UnM0COTm#{ZEhZMyOy`kEF7Ml);g|yxoJceVh)wvnSi_V zy!|4~gFmoaj`fu`;Xwxfa4Som^Z4yVVX*2ZPMV#uCMV|6%zT$t(hT#JacW8*=kC5j zM}W-jOM%U3PSmsaFGqKMUcT63+G0}MBuaz(gn=J9ZTvEFa;|)m1n+c{Y5N-FRthCV zoKv$a)?I^!*l@rwBuwh^jM->l(%r4Dm&p!_K6DEyT++Ts=gK;%X8SW_e+bmA0+cV+ zI+r|8wUBJBg#%tjm+h8(=9xwsnr&_Gxt-eJIg3`Nb-2usQpRCEb=N+GkDN3T2cbHtjVCS}!+3ye@#T-t26W&Ci0RsX6Cdu--aVtL)mO z)qg_eOlg_!8_9sF-&4mShPd60FPI zJ~~2%$)uN9F1(&Wx{OJ8Cd6tOs?X9pV3dXlJ9yfi$+d## zhb7OWZCPh1hg+BiM)E7M2Jm`Lb1h|PWM?goiy0<1ZZf8# zCa&0MK(xoe+?Y634zmSqXWP$wV8Gr;(I~~R@LQWTG5levz*@>-N`$TIf!M<`W=jUl zP>xN4N*L1owyb7uHg}|%q^LB&SiUOVjN_%_A-W$pl88eC0^hh4ydBMBsD_ofC~(cM zt42n&FhoUK4bmgH*b}Si2_cK^$3v|JvMe1$9f zu{x7OR(ixG`Pj-h>MH#XR0e9rey4he+PVT7*4cZ1&+q@c&(W~TB*&_8A zeqBU^!PCXx<8O($cPt=a8D=M(BG&~O5sBHI{Tc(q4t?2tjK66zlWxo$Y?wrQAk&Q{JeJP7`w$7e8W&?R|_(}%PXF1AOvt$rz}j3OFQwmJarzxTrTbVm@#oP}AEc=bMYx%IEnO>%?rc1D`G zb+45})SH3B4YK;;ZgZ1!fPhTAU`izo8fX|ELSyz` z%y1SDxxIF8BGOWk=L>a7gec9Lxa=kJ{_G}nu7^EL`F#c`;JQ5q5D;S%noB-J1ZK4g zA!u~LN$tj;>PfIo4u-ARk?2^})k27kO{Gg<$wiaRlU0_&dP5ySH;;Rms0x*oYgOwb+g}-6DftAw}7|73aWwqB*#0Fk%#g=akp-mZ*fc1z)Y>^KLBh`Q##f>rQ z-}MC*tYTl5?6lfgzD@HszA9)Jg#{0hJr`kcbh6^y8_;REP5o;10p*4{A#Z)neJ4ls zc7GrDHQm>i{fM5@2!43TE9(}k%#x3s?-f;fUB+lVeVcX+v(N^)%Q2CUVxWvR*P1Hq ztde+%o;P*yp?+CoF3Y{J%gcFW_AlOJp1JLfOgiqO@C#^@fOAJr&&x%Hn*qL5ptsfs zuQ4#AJEnTW?u62?WYLRNvTS{s>Dx4ptHdjk5XXtSdW&mtt<=~mx;e0@Cl@TJ+RVQ~ z?qHXcrGmykp-G^^&~NhCBF&sSK61RVw4^dSqe7G&Dxt(4zd=m0H(6KlK^yvU_;~Rw z%|K5e5ks|gb{MDEmT#sy5DlhYrFmPkBb>Gr0l(a8CAo}1f|Poak$l!oZQePUiQ1uZ zDY-Sj=>k|2$2lWkE!Kw@Pkeb<5=Rk#-k?YB66SsRBC32p67zXLiIsYbravW26gniE zP^UQf4)x#`Yka6j8EfJ2s6z;ML5Iw9XvK*}t90VTh3x3E(M$el^+Y(>&s&7nY`S~H zvO-2^RU{uJSa$s@7GCWkuYvDp>k1YI`uc?7)Z@PuF(Aq`A3HBmv1LwlJ3fpf54(k9 z#ms-#vRG=NpC0`@_A+0kkN6p6`^}VTNcI{37tZ_ep3pK}o-68s4rqQC2$*Mw`*f7Z zsf?}!b1zG?$}noMj`gH*a=XHoyYD-EWb;f7UU6j;Ym^lqFd76Zshwq(OcL)-*D<*r>u&zKlR5PU!Ub$Q6^?!y|+2b^6VOSt-_^ z%Zj-Kwug+V*7zm|^-FH%If>ATTAX%Y2v4`;K3YdBfAuY*jdSIZdth&*-na%thggU> zP55NW&^X>@q{{1@91&BWP^0ykyA)$7v^*l-h%!9acAw`0CMETx06Yk#7#z8THCA+7 zhUPF&qhd0}h4K`maf~H-aJiLv1LF*6Q$UPNE#MTmqBsZAE**)!*B}OgptX6AFlbH` zelmf<&@?UQz0J^Ih~f)wfk>SPh`Xxe^0mjV3yem;!b5_K zkI%6kdAHdv<@x33tG5nv1oE{wa}q>mujS?BRlQt|r39Vv!+WOtjvcSZ+4BY6Ub}eY zTaMje$@;HO3L4^Vkbg<B<2*zN2goBm-=O4XuI)X% zz8YgjIC}QMPWaXS^%mVpR&{YJt3D!y0YvG}?3bJEHi1&w582Qa?-gh{CC8h%AzxQq zy0%a@4Tu&V(W81d;YXNj=U5SLFRQZy zcfd)~HK@`fUIVR$Ge@wFD|9>2YRaIGqp3+MM+JK>8dKZLGigfG+99ioRVoRoVslF# zUm$_*H`j!FfE8U+2;sj5Ps^r{%!G){lSvojYDmo1kg!e{)m#$eawb0BFrOMpvm-st zE4~3bUKcf{$4dbq;}I=4i_+P_;=@A72OQtmpG1$@Z+u^ck449?ZOtgqVY1@ zZ{+Z~!Beiu8ARl`GonjbyIZ{;AYB-|Ic*t;Fw5UH66Tu$L71&IVN2jhJbyt8ssWy+ zx&@ttD$isCH5DnDR49BffwHnzO;I)ANC) zqJa+%=sRO~U-7z6>44p9f(o-b!H}`kqdQ`HeCWOL)NHn# z3#r4>m3ZUNbbZ8LV;grw{=x!j{nk}jl*AJdC!ymr(jA)7k^G;sgLduwG1(3$&BUS6@z zUh0GLzCvxTO~N_kT6+R&_HD=U$IC-^yI{#ZLn4B$OrtpNPzNnYu)JlGebSoAke5EP z(|yL~wczW7k}q&ua+zxN(p0h{XNtEaZj!t^hnDDG$;Sd4O*Msc*C1l6A&8wABG$!s-l)&{$j{CzLL{$%t%8a?!@hpW!{iWjf>Yoo7&hK0?1+v^3&y z&upm#Spa!u@s;{3_SKFk@3T90D$j8HT$j_XI$-pnJ>Cvt@Fo9`Y5SSwd!D{C0eA2~ zRigX#kWuD=`g*hEgNM(_;~R>Wg-?Rv$IJMlT^+(j35&_)LT~O1YYQuAqk+Xx4 z`4!k>wiaW~7pr$8UyIR9jtj1LK_-i_j(D&E-S>K^Es^9I(%H{|quk_fUgw4=P&L2P zI^jclwgL@I zdvSq#qc{xFX@(SE7zCq_{GR1L4(La2c|HzoaDIqXWy|ca1$miYg`gH>Nix5p-6-1- zk*@|y-JSw;V*CLbw`dN$>57KR1!tJ&%&@jw(lkFDBB^A3w<1jD8|{#Q!?3 z%>XaRcyw7XRr+3S1RH@dXwNIbnm{#eR2H&ej`zEwwdyEV}2i}E` z*{yiz!bZG-S70@4O}2YL3m<(S$ZFVpEpW#!a4k=GpPX)f1J5&&12C*o0ye^#{)MTE zgx>%VPv9>%2;0BxR;BO$&u6;tu^#(y4-A_k=p(cbA9P$+b`XP{8^nMRvR!ZsgQF?# zbQz1I@EP%qrW;|fM0PNK2fY5v`r@3bXdeb?myaCRORF5aE4GUn?QLIyUiF56p-y5| zCGL}pD>D=mhC9QOp((^E(lBlvcvKH?7jHPRb~*K+!&VbEY%drr+Ygg#)R>vtuNwLj z+76wiuCaD)*;U<3y(4TrPzRwC>$-EOHV7?f*@@9_*qCip-|mcd(USsKmkA~G+|_>@ z+Gh#ecb(g`<6Ng=?_8`OYl0Vs6N*VjNVaiEd8iZHUOtcg44r?mpPo_Exo6d8a$Bow z3BqraMah5_^R))Eo{eTK%=0#M!S@ZF^i%PRa>k6ASgfv5uH6zZvO{UFS0g`vyj^KJ z{aQ$NtqkVqIvtNghbP{n2u5FmyPg<3uw8)~mj-%E#UzEJ59wRCZW-G2wIjNeVPTtz zE_9eUu*FStC}J&xdLh$f+&i`TF5xk_NRNS8tw;@|`chYF(@0;&-=5lb`oDBMKv8nZk_Bn;-R z_kk)ffhEmn;VKZG<=I7$_-~yzU}T+&u$ab}xCx7_7MR!sK7M4L{Za ziY3XMotWpD>CIu({=}D4bll)52GHkI0hvWyX=|=123Z2G~+6Oe6;8X%oW2>KhkL(BxYwr)y4F zz3F-$z5Umd9m@;Fqw`gITq}^c}ShpKft<&t#Fi5X{#66orY0f}mq9sVL zH*2O`a$4`;_ZWZ5F5vL_U}=7%jdqhF3BvK%i+}YMESElo+jdiDImb%~kYhE|^wpYV z9!vJlBCa~cb2Zu%R=rTRC3wF#?BV3klJX(m%<(U-XUsZ>-i4t_e)Y>2DBm=7>IVv# zMW1ly$tX$|KAQAlRy0P#ghKzo0CVP|3BsS%RKxd4?JVZt9!lEM<=#WHrDl7q&y{Le zGAKeDgVP2hdM7%921ZA#(8vj(3`GrtyquSDx+o)f!?p&}&WFmd8jT$T;x z0ZcEz>y^tj8;@}~m6yq7NSMPSCk1yOPT(Z)0~gnlKE|PKW8U?}pmQ_r64>~$V>$IXD3UmIY)&R|H#^@?lB$Ry3=4u+4VVCNa7WV4s5o?}>7y9N1iI6^pNX6i!4 zXI^voflM;=zo!^_oBH_{4hFdaj6$|fdoVU!XKT`2$eiarh6+PFakM0!_8N4)hrl9_ zh(v&IoM8YSxMWCy4`S1Yso$-X~g7AWAwNqd|hG5-WL{GUJcQm=1cq9A{$Lf#)gT~ z#S;v}RO;QiO)(hDC)^ssSZv1r(Ra|l?m#$^Z7942h>BuC0|9aUKCJ&8E9T#9f&u~q zI$|lJJix(7F(&Q!WU-Kyio>7+!&9&^sgB7QC(xj!p)f3($Joh2ahs8(8BOYx zBFZVJg|@m=8I@TmAZet2pK@x6WM{*>>9n7BZ6xRl?$h&B62@ zAckY(`YMX?u|O&r*<8jtvAk;Cfjw{Nyay{zjNU?Cqg-c)n_YyXV>FUb-#&y zK3}ldPx+zj3buc~F?v-Q+JR^TO>XcY!Pz#CE9ZE7!&9?UOPS8O$O`AGT4aRgy(3F{ zr;#VRyZ2%YK-&gGM0Vlb*^7Mr;kRntx|pYeh|vjhd~&@sZ{#Yev%8hAgp3%k&V+4M0v^eO$__iD zj{53M-z;|ZJTMnlj1_Mv$ZrrLoRk1zj%+AfG^lsdXVw-`ylX9k#hqqZi+?>p`Y6Tg<9Ydgr!N1wjyeIZzZj%xfsGG%lhUg7GP(PJ=HbS5Z$_mP|f zjKg_m5N1o<7Or8!>b4L}gUbg(kK zlLv;*vYe;dW%@M|3t9(sBJS-UsyEXtJ5rVr-y>JS-puI0-puMSqhe#sJwC8CW7Y9zxoj)blmO&LRZU-w})h;h5yZSZ%D#DWIVP{N~Zg# z=#_?B9}Y9y_~Lx#AP|wEyE_BB1w%d^BUFj{g^E@P1)(A2S%!`ITcIWxy?6_AO#zya zc4KpVV{>77{ygv!N3~hvOw)ANTM|v&Cao7(++vM5ustP*^7Fe)#ND^=Xlzm@+?cPB zHeo?BE{DxyRSS<*1**1HJ81=$_xmP4Uoh}k-%b6ba`f$#QfyiaY71a)CIHOMG`|mA zzd2?8eA*&hUj6?1CwG`x14fr-G(;|98 zeI#qU$qbf=5^@J@>3=+Wk%uDgmXyYEpLXiD%E8qB==S*REh06g-m6z~QiMJN@OShX z+1mjjDdIG_QC{i2v@~Sa>K>=>8>ri_x2keC+CspgkX(n&td;rmtA?%;S3dg{D*GMM zQtuT)b?ImgtwR|!c_jE$56}pfyF^rkZ8PSPNOU4;sq!2tujc-ge2U+~_SGYRS`w)Dhz*RzvdialDZ+5wRt(0}qn2 zHi3;aB><1wVEp=)HvtpRfDCf&cFD$@E>oXkXuo|IhE2jpxvd&DiCVLZB(&t>I z2Gc0APSg4QuLer3n>+nUzY@Ifcfe$f)Vhm5G;7%*dPRM|RM66P%$`42)3}@Drw(__ zxR??AVA?dWswDl{&of9HBZ=zxOu6N)ZGjxceWwjpabp3D+zYI#^>mW(ZhHrf-5>(z zlKK0ud!1Z7EBQ(e>e&Vss-K-0x%X5HGl~6cBC1u!7=oBMEp!!nvLi@oidDudLs$a* zUu}mQwo%s6tlw@cv4}CjTtiFNa=|c>Z@zqqkCnJ`ECIJr+ao_3MfgZ(Sh#`r9D}S& znTu;xYq?y9?bKdy3unJFiVQHS+U=)CB$8k?mpb*u zJfbEN@xULK<)?ig|Ct6pe1xFKfI*-VX8V1>k#Oc$5*DIvXULpq=TNsus7(3oe79rk zq5Nfvm7(M_>%r@cWv|lLsd|CaxnXMLgg2S8g;@CF-35QuoU2b;wRd)}53xJAM{(_NQ;||h zB=7)5}m37tuE{8(oj2!aw#7Zh`^kwqF7SBo?U?E?c zhJ=?;(W_A)!T__zak@fEch%1Kr(;gZU6Osh-_F3j8!N|}!oUKVx6oL9h?~pWR+iQq zh$6hGjH(m-+GwxCmHYzCy4~buN!shUZO(OB#@ah{(#CNYNR8Dp6~Ce5(Ufw(6Hn;Q z5r++5wA(Q1>Uo6}KBKqx$+QB&9w;=j@Tt9>V zTEBwhXgdc0k4QJb7s0;@V<(_*U}>W-Vr*k;CvUIwz5f6D`t4CNmq%6xoRY7yvaU7~ zgMC*wC+5qi1;Jm;hX9Qjg%oTa$2wOptui^SH#=`u^bl0ng%Tr4_pj_)Wy{f}$*#=r77`8Z=m`G^)G;3-= zk`1G0!HG1sB@lD4n2bssGhh{?*7ChzJntBSq$5(p5bD@JmOztt;HBkT!7MoNOk$~4!>lz} z8xvtfy`RCruS!rkSIcni@3=A&C)XGmU}m=-=|({tbWzDC2jSqHbVxxrqNa8Q`DnKc zSqBn26Jhr3G(**$f%YXph0JLOIf=ht!)wz?ybiOQbuvnf41Y1;bn>1Q6rG+-#eE2Y zm$Rcv(RhlvOUwQBOmfD9z@&a|650UOI+4YwFj?;*@+8a$-!H=nct-jun_Qq&5=1&l z>qWcKtdZ_O+Y~4l9E^{0rfr8 z!Z@;uO7|8#c$kxZSO3ao!PKri8SIUr0BY*%>iig*b4{leF0DePS~$mf>W#1GVES{L zvuj`BZ`!-1Q@g2&E;6Aexxzqwvs)(n;WOS}U0l0F8n79k6lewac>2?!$sT=pWEydI z%2=4x3D*?FR~PWo>;u=s&S&Y=jdSb5l&dAh?hC^e@A2?H z#k@oQ_`&_=`E%%rpbPSevfC+HfUwhxUSq5vL@np0$PYSuH5Xi?C|?IUnLw`TFKqC$ zvge|4qO}NDofooQ@ly8;f)8NBsuaU2SxDwM8O?lGLOB8-^b=G<+X5h^kjxp9v!mgk z9T5b8;JU|ciR)m!Mj%mba&CB8DmG;+O6!oR)Na*4Y!Em3$EuBX0ppW!SLyIp}tB3Lc5y#8vg&`qc7j%Pg1N~)&IFFn3 zSGJfh_`i-Ju|Ql&-#n|o0LEyJ-^XZqXIndc^M7MgNQ)Vg=;A{O_&8T=URyU~GA+Es zB7iK^?T;RXhW?uF)xJkE-efchGTEfSiiENcG=4`Q61g!#A%C}OD%1JL$C1>=7SEQp zXC2SX5(wbKiOf*4RQ*PP%}_Ii2|Nd1l6{2KTeyqjs~hSQ%Um$TTaj8u3~}YOiFb#}Vb@Tvt`+q2fwGX=^3*mQDXf1&E{)4eX7Aiqk-L z$Ypz+fe@%dCXg_2u4pDs_p3f-6z|Pv66R$_9#y5i_{<#q$0kmtwc{1ArIWT@Mu4z0 zhEqw|76|NL`dA7VH8Wp`c%w|kwA)sIb6l>;4FLy_W^YtsB~c;2v%RO|1ME0JN>J_S zR>J9{Qrr3tQZuwcO@o|}Smn1})OfMBXC=|u(SnZ9WOEf70iG|i)u4)aOpnwaL4Ivg zT2vz+a6of51B^wCzc=Ym)9!c2>fe@^@8nl4CtjgE$WWp{+jcA|Fe9_!(6b)6F=0rP zBqv6hLmI%lHuH5g#i`pa(%$jjZiJHY+<@NzzPQZi^?X5$C(`k+Q%~J?Qx{h~JsyCq zfciwR7FikRMzc*eF&${8Xqh3Bl+!P=XZ;jftp(`0K8%r;IB@UdX@%XF-BH}}xJoR) zCHR7z_0n86)xd7Y-*2h%RaUV}bkJPVBSBs*z4Van!)G)%LdDCjM1g7W^hwAqgnwoqFN{ahS1VOpL#z5IdLpx4sY^qT^T8S4q}i zcEch!1ldo-p-?1KI_Wnvs$Ctf-3%S8n>pGa-0tBB0)!Dqf|w_eP{)0O#H#q|0<0uE zD!djon5YCg61}*9dxf2>W&MKgf$<>3=%-RFrvwNF$I>RkHAoEmi=9bhMv9|z+bRi7 zizyZ5(e!dMF|4cblv$=*`sk+*%^u4ANwsJzLjf_Tonr2aI>$Oe&(*Q1L(UYm24cH2 zCaP^b#90;E=%BclGz03oP30NL6m#Ah)G38T!AykZQ;IOsp+iBbhO^&cu)_szTo}O9 zMv6;2lfXzf#WU!4Nm(Wrl|hOz)-1HRqf$zDy3D7j#jXxUx0GxXVNSlP)o9U}*gbN_ zWW8OB566+!z{GRsSgs;3kPwhW*Pm`{HAhDO6!i?|(D3tmT34uQ&$m{r^J(fd17VBmlO53H<*I809%Yxf}ul$Pr-T0}%fw z>^)$3_+X4=ji5Q#d^XuyB+uBNNTWA~pEw%78 z@58WKBHu!2-vSJJzvdkeAZq%Dyet1D%>l4=7#JJc1L9``V#)tG?|Lr7t1*Bo;Rd`* z^nYg@@T~E^L--@~)Akets709lw~XgG(>EyrG7bc&oo_?N-&c+I0_q>pr7R8qYb}i0 z9EP9*98D|$W&U<9>hG(@+Z><)@`qaZMfUE`#b;lsTgC>wVn={cfZ%UHz_Z4?7m(jS zU;<7B+G(4a{TXe!Ln^o%P?_%lmHBHs;RE``AJ7CWE$zPPZdgfc8(RR3u0PZ^o^}DT znR=2*K>s2J6!n{C!rxbo_X~jN-yfjAcL8B1eO>$igin8p>W7tETm?WC0H9L+4GDPG zc#8`D5%sT^;yd=YO#iteo@(y?4PE2SFY`y-@74O>hM%Vzhd=NL0R#FUO8-mK|2M_M zr?v4^Kko+%welZX{&~cCDx32I&iBoKX3y^f@E>Q;pY!)^ck8L@%@07-xBp!O=PAm! zRNr37Z`U{7n7^)X^BAV~FQxnz!{%w?rz$dkC$I4q`#tgBegZ$O*PmElpTa*?2KfO$ zsry^reuDk}b;?Z^FOFcP5z1MzXYCt3jZ`_`VV+PvwwpB-V*;5LH#M!)8MN=sPygr1=U}b_P?s@ zY5d9`B!Q0qg5;m0Sw1b%({O)3$a-Ap#72PxsJ&ATyQ!hWvYH`V0EcJL*ph@pSL< z2NhY>KT-XUx%BCl-4ED+>VJa$K4ARA2Hw*GJT>h9U>dCdjp^z4!%ubhKMM5J*!+Vg zt?@USpJ2Zi==jD1h7jz91(n*Rm \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/gradlew.bat b/spring-cloud-function-samples/function-sample-functional-aws-routing/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega 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 deleted file mode 100644 index ec0799a10..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/pom.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - 4.0.0 - - io.spring.sample - function-sample-functional-aws-routing - 0.0.1-SNAPSHOT - jar - - function-sample-functional-aws-routing - Spring Cloud Function Sample for AWS Lambda - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - UTF-8 - UTF-8 - 1.0.27.RELEASE - 2.0.2 - 4.1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-function-adapter-aws - - - org.springframework.cloud - spring-cloud-function-web - - - org.springframework.boot - spring-boot-starter-web - - - - com.amazonaws - aws-lambda-java-events - ${aws-lambda-events.version} - - - com.amazonaws - aws-lambda-java-core - 1.1.0 - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function.version} - pom - import - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${wrapper.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - false - true - aws - - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/java/example/FunctionConfiguration.java b/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/java/example/FunctionConfiguration.java deleted file mode 100644 index 554133da0..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/java/example/FunctionConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -package example; - -import java.util.function.Function; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.MessageRoutingCallback; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.messaging.Message; - -@SpringBootApplication -public class FunctionConfiguration implements ApplicationContextInitializer { - - /* - * You need this main method or explicit example.FunctionConfiguration - * in the POM to ensure boot plug-in makes the correct entry - */ - public static void main(String[] args) { - SpringApplication.run(FunctionConfiguration.class, args); - } - - public Function uppercase() { - return value -> value.toUpperCase(); - } - - public Function reverse() { - return value -> new StringBuilder(value).reverse().toString(); - } - - public static class RoutingCallback implements MessageRoutingCallback { - @Override - public FunctionRoutingResult routingResult(Message message) { - String payload = new String((byte[]) message.getPayload()); - System.out.println("==> Will be routing based on payload: " + payload); - return payload.contains("uppercase") - ? new FunctionRoutingResult("uppercase") - : new FunctionRoutingResult("reverse"); - } - } - - @Override - public void initialize(GenericApplicationContext applicationContext) { - System.out.println("==> Initializing"); - applicationContext.registerBean(MessageRoutingCallback.class, - () -> new RoutingCallback()); - applicationContext.registerBean("uppercase", FunctionRegistration.class, - () -> new FunctionRegistration<>(uppercase()).type( - FunctionTypeUtils.functionType(String.class, String.class))); - applicationContext.registerBean("reverse", FunctionRegistration.class, - () -> new FunctionRegistration<>(reverse()).type( - FunctionTypeUtils.functionType(String.class, String.class))); - } -} diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/application.properties b/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/application.properties deleted file mode 100644 index eed9c5e95..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -logging.level.org.springframework.cloud=DEBUG -spring.functional.enabled = false diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/log4j.properties b/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/log4j.properties deleted file mode 100644 index f644d953c..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/main/resources/log4j.properties +++ /dev/null @@ -1,20 +0,0 @@ -log4j.rootCategory=DEBUG, LAMBDA -PID=???? -LOG_LEVEL_PATTERN=%5p -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender -log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout -log4j.appender.LAMBDA.layout.conversionPattern=${LOG_PATTERN} -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.apache.sshd.common.util.SecurityUtils -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.crsh.ssh=WARN -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN -log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN -log4j.category.org.thymeleaf=WARN diff --git a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/test/java/example/MapTests.java b/spring-cloud-function-samples/function-sample-functional-aws-routing/src/test/java/example/MapTests.java deleted file mode 100644 index 289a8c9ff..000000000 --- a/spring-cloud-function-samples/function-sample-functional-aws-routing/src/test/java/example/MapTests.java +++ /dev/null @@ -1,31 +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 example; - -import org.junit.jupiter.api.Test; - -/** - * @author Dave Syer - * - */ -public class MapTests { - - @Test - public void test() { - - } -} diff --git a/spring-cloud-function-samples/function-sample-gcp-background/README.adoc b/spring-cloud-function-samples/function-sample-gcp-background/README.adoc deleted file mode 100644 index c561972a1..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-background/README.adoc +++ /dev/null @@ -1,104 +0,0 @@ -:branch: master - -=== Google Cloud Background Functions Sample Application - -Google Cloud Functions supports deploying https://cloud.google.com/functions/docs/writing/background[Background Functions] which are invoked indirectly in response to an event, such as a message on a https://cloud.google.com/pubsub[Pub/Sub] topic, a change in a https://cloud.google.com/storage[Cloud Storage] bucket, or a https://firebase.google.com/[Firebase] event. - -This sample demonstrates a simple background function which triggers from a Pub/Sub event. - -===== Test locally - -In a terminal window, run: - ----- -mvn function:run ----- - -In a separate window, invoke the background function by issuing the `curl` command below. - -NOTE: In this sample, we demonstrate a background function which is triggered when a message is https://cloud.google.com/functions/docs/calling/pubsub[published to a specified Cloud Pub/Sub topic]. -The `curl` request simulates sending the message that would be received by your function when a Pub/Sub event occurs. - -In order to simulate how Pub/Sub will send you this message, we use a base64-encoded string as the input because Pub/Sub encodes the message data in base64 in the Pub/Sub event. -See the notes section below for a more information on the Pub/Sub event structure. - ----- -curl localhost:8080 -H "Content-Type: application/json" -d '{"data":"aGVsbG8="}' ----- - -In the original terminal window where the `mvn function:run` was invoked, you should see a message printed. - ----- -Received Pub/Sub message with data: hello ----- - -===== Deploy to GCP - -The steps below will demonstrate how to deploy your background function to GCP and have it be invoked by a Pub/Sub event. - -To complete the next steps, make sure that you have the https://cloud.google.com/sdk/install[Cloud SDK CLI] installed. - -1. Create a new Pub/Sub topic. This topic will be used as the trigger for the background function. -+ ----- -gcloud pubsub topics create my-functions-topic ----- - -2. In this sample directory, package the application by running: -+ ----- -mvn package ----- -+ -You should see the JAR to deploy in the `target/deploy` directory. - -3. Deploy the JAR that you created by running -+ ----- -gcloud functions deploy function-sample-gcp-background \ ---entry-point org.springframework.cloud.function.adapter.gcp.GcfJarLauncher \ ---runtime java17 \ ---trigger-topic my-functions-topic \ ---source target/deploy \ ---memory 512MB ----- -+ -Notice the parameter `--trigger-topic` which topic will trigger the function invocation when new messages are published to it. - -4. Invoke the background function by publishing a message to your topic. -+ ----- -gcloud pubsub topics publish my-functions-topic --message="Hello world" ----- - -5. To verify that this sample background function was invoked, check the logs of the background function on GCF by running: -+ ----- -gcloud functions logs read function-sample-gcp-background --filter=Received ----- -+ -You should see a log message that looks like below. -It might take a minute or two for the log to appear. -+ ----- -function-sample-gcp-background-2 h8q1jt46069r 2020-05-19 19:48:27.960 Received Pub/Sub message with data: Hello world ----- -+ -This log output is produced by the sample background function, so this entry in the logs means that the background function was successfully invoked. - -===== Notes - -One important note about the Pub/Sub background function provided in `BackgroundFunctionMain` is that the `data` field must be decoded from base64 encoding because Pub/Sub will encode the published message in base64 according to the https://cloud.google.com/functions/docs/calling/pubsub#event_structure[PubSubMessage event structure]. - -[source, java] ----- -@Bean -public Consumer pubSubFunction() { - return message -> { - // The PubSubMessage data field arrives as a base-64 encoded string and must be decoded. - // See: https://cloud.google.com/functions/docs/calling/pubsub#event_structure - String decodedMessage = new String(Base64.decode(message.getData()), StandardCharsets.UTF_8); - System.out.println("Received Pub/Sub message with data: " + decodedMessage); - }; -} ----- diff --git a/spring-cloud-function-samples/function-sample-gcp-background/pom.xml b/spring-cloud-function-samples/function-sample-gcp-background/pom.xml deleted file mode 100644 index 86b3a064b..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-background/pom.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - 4.0.0 - - io.spring.sample - function-sample-gcp-background - 0.0.1-SNAPSHOT - jar - - function-sample-gcp-background - - - org.springframework.boot - spring-boot-starter-parent - 3.2.0-SNAPSHOT - - - - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - 4.1.0-SNAPSHOT - - - - - - - maven-deploy-plugin - - true - - - - org.springframework.boot - spring-boot-maven-plugin - - target/deploy - - - - org.springframework.cloud - spring-cloud-function-adapter-gcp - 3.1.0-SNAPSHOT - - - - - - com.google.cloud.functions - function-maven-plugin - 0.9.1 - - org.springframework.cloud.function.adapter.gcp.GcfJarLauncher - 8080 - - - - - - - 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 - - - - - - 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/libs-release-local - - false - - - - diff --git a/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/BackgroundFunctionMain.java b/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/BackgroundFunctionMain.java deleted file mode 100644 index 753fe6322..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/BackgroundFunctionMain.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.example; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.function.Consumer; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class BackgroundFunctionMain { - - public static void main(String[] args) { - SpringApplication.run(BackgroundFunctionMain.class, args); - } - - /** - * The background function which triggers on an event from Pub/Sub and consumes the Pub/Sub - * event message. - */ - @Bean - public Consumer pubSubFunction() { - return message -> { - // The PubSubMessage data field arrives as a base-64 encoded string and must be decoded. - // See: https://cloud.google.com/functions/docs/calling/pubsub#event_structure - String decodedMessage = new String(Base64.getDecoder().decode(message.getData()), StandardCharsets.UTF_8); - System.out.println("Received Pub/Sub message with data: " + decodedMessage); - }; - } -} diff --git a/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/PubSubMessage.java b/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/PubSubMessage.java deleted file mode 100644 index 01b5084fa..000000000 --- a/spring-cloud-function-samples/function-sample-gcp-background/src/main/java/com/example/PubSubMessage.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.example; - -import java.util.Map; - -/** - * A class that can be mapped to the GCF Pub/Sub Message event type. This is for use in - * the background functions. - * - *