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 index d6230713d..daddbd8f7 100644 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc +++ b/spring-cloud-function-samples/function-sample-azure-blob-trigger/README.adoc @@ -9,6 +9,16 @@ The Blob storage binding is part of an https://learn.microsoft.com/en-us/azure/a === 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: @@ -27,11 +37,14 @@ Use the script below to run the function locally. ./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]). +Use the https://azure.microsoft.com/en-us/products/storage/storage-explorer/[Azure Storage Explorer] to access the Emulator Storage Account. -NOTE: https://github.com/Azure/azure-functions-core-tools[Azure Functions Core Tools] version `4.0.5030` or newer is required! +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. -For some configuration you would need the https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator[Azurite emulator] as well. +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 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 index 9aaad52f7..2eaed4fda 100644 --- a/spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure-blob-trigger/pom.xml @@ -33,7 +33,7 @@ org.springframework.cloud spring-cloud-function-adapter-azure - 4.0.0 + 4.0.5-SNAPSHOT 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 index fe209a965..ce0ab0212 100644 --- 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 @@ -30,7 +30,7 @@ public class AzureBlobTriggerDemoApplication { } @Bean - public Function uppercase() { - return payload -> payload.toUpperCase(); + 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 index 302e07e34..06a26c7f4 100644 --- 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 @@ -33,33 +33,33 @@ 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. + * + * 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; + 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-triggerinput-java/{name} below + * test-trigger/{name} below */ @FunctionName("BlobTrigger") @StorageAccount("AzureWebJobsStorage") - public void BlobTriggerToBlobTest( - @BlobTrigger(name = "triggerBlob", path = "test-triggerinput-java/{name}", dataType = "binary") byte[] triggerBlob, + public void blobTest( + @BlobTrigger(name = "triggerBlob", path = "test-trigger/{name}", dataType = "binary") byte[] triggerBlob, @BindingName("name") String fileName, - @BlobInput(name = "inputBlob", path = "test-input-java/{name}", dataType = "binary") byte[] inputBlob, - @BlobOutput(name = "outputBlob", path = "test-output-java/{name}", dataType = "binary") OutputBinding outputBlob, + @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 BlobTriggerToBlobTest processed a blob.\n Name: " + + context.getLogger().info("Java Blob trigger function blobTest processed a blob.\n Name: " + fileName + "\n Size: " + triggerBlob.length + " Bytes"); - outputBlob.setValue(inputBlob); + + outputBlob.setValue(uppercase.apply(inputBlob)); } } 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 new file mode 100644 index 000000000..089443f7f --- /dev/null +++ b/spring-cloud-function-samples/function-sample-azure-blob-trigger/src/test/resource/sample.txt @@ -0,0 +1,3 @@ +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/README.adoc b/spring-cloud-function-samples/function-sample-azure-http-trigger-gradle/README.adoc index c6f4dd39b..395492529 100644 --- 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 @@ -35,6 +35,8 @@ 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] 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 index 7e2b83995..2b83ff36d 100644 --- 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 @@ -28,12 +28,13 @@ jar { } repositories { + mavenLocal() mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter' - implementation "org.springframework.cloud:spring-cloud-function-adapter-azure:4.0.3" + implementation "org.springframework.cloud:spring-cloud-function-adapter-azure:4.0.5-SNAPSHOT" } tasks.named('test') { 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 index 83d1997e2..dde5a88a4 100644 --- a/spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure-http-trigger/pom.xml @@ -36,7 +36,7 @@ org.springframework.cloud spring-cloud-function-adapter-azure - 4.1.0-SNAPSHOT + 4.0.5-SNAPSHOT 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 index 7ff36d5ce..8dccc6eb8 100644 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/pom.xml @@ -16,8 +16,8 @@ Demo project for Spring Boot 17 - 4.0.4 - 3.0.0 + 4.0.5-SNAPSHOT + 1.0.28.RELEASE example.KafkaTriggerDemoApplication @@ -33,28 +33,14 @@ org.springframework.cloud spring-cloud-function-context + ${spring-cloud-function-dependencies.version} - spring-cloud-function-adapter-azure org.springframework.cloud + spring-cloud-function-adapter-azure + ${spring-cloud-function-dependencies.version} - - - - org.springframework.cloud - spring-cloud-function-dependencies - ${spring-cloud-function-dependencies.version} - pom - import - - - com.microsoft.azure.functions - azure-functions-java-library - ${azure.functions.java.core.version} - - - @@ -104,10 +90,17 @@ - + + + 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/java/example/KafkaTriggerDemoApplication.java b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/KafkaTriggerDemoApplication.java index 7b8d10a94..bb01e7c8a 100644 --- a/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/KafkaTriggerDemoApplication.java +++ b/spring-cloud-function-samples/function-sample-azure-kafka-trigger/src/main/java/example/KafkaTriggerDemoApplication.java @@ -18,7 +18,6 @@ package example; import java.util.Map; import java.util.function.Function; -import com.microsoft.azure.functions.ExecutionContext; import example.entity.KafkaEntity; import org.springframework.boot.SpringApplication; 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 index 67973fa4e..2e7f33b11 100644 --- 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 @@ -16,6 +16,8 @@ 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; @@ -24,35 +26,39 @@ import com.microsoft.azure.functions.annotation.FunctionName; import com.microsoft.azure.functions.annotation.KafkaOutput; import com.microsoft.azure.functions.annotation.KafkaTrigger; -import org.springframework.cloud.function.adapter.azure.FunctionInvoker; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.stereotype.Component; -public class UppercaseHandler extends FunctionInvoker, String> { +@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, + 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", + topic = "output", brokerList="%BrokerList%", - username = "%ConfluentCloudUsername%", + username = "%ConfluentCloudUsername%", password = "%ConfluentCloudPassword%", authenticationMode = BrokerAuthenticationMode.PLAIN, - // sslCaLocation = "confluent_cloud_cacert.pem", // Enable this line for windows. + // sslCaLocation = "confluent_cloud_cacert.pem", // Enable this line for windows. protocol = BrokerProtocol.PLAINTEXT // protocol = BrokerProtocol.SASLSSL ) OutputBinding output, @@ -62,7 +68,7 @@ public class UppercaseHandler extends FunctionInvoker, String> { Message message = MessageBuilder.withPayload(kafkaEventData).build(); - String response = handleRequest(message, context); + String response = uppercase.apply(message); output.setValue(response); } 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 index bd4be3574..c3beccf22 100644 --- a/spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure-time-trigger/pom.xml @@ -34,7 +34,7 @@ org.springframework.cloud spring-cloud-function-adapter-azure - 4.0.0 + 4.0.5-SNAPSHOT diff --git a/spring-cloud-function-samples/function-sample-azure-web/pom.xml b/spring-cloud-function-samples/function-sample-azure-web/pom.xml index b24acfd90..0c6937461 100644 --- a/spring-cloud-function-samples/function-sample-azure-web/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure-web/pom.xml @@ -20,7 +20,7 @@ 17 1.0.28.RELEASE - 4.1.0-SNAPSHOT + 4.0.5-SNAPSHOT com.example.azure.web.AzureWebDemoApplication