├── .github
├── policies
│ └── resourceManagement.yml
└── pull_request_template.md
├── .gitignore
├── CODEOWNERS
├── CONTRIBUTING.md
├── CodeQL.yml
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── SECURITY.md
├── annotationLib
├── azure-functions-java-library-2.0.1-SNAPSHOT.jar
└── warmup-httptrigger.jar
├── azure-function-examples
└── local.settings.json
├── emulatedtests
├── Azure.Functions.Java.Tests.E2E
│ ├── Azure.Functions.Java.Tests.E2E.sln
│ └── Azure.Functions.Java.Tests.E2E
│ │ ├── Azure.Functions.Java.Tests.E2E.csproj
│ │ ├── Constants.cs
│ │ ├── Fixtures
│ │ ├── FixtureHelpers.cs
│ │ └── FunctionAppFixture.cs
│ │ ├── Helpers
│ │ └── StorageHelpers.cs
│ │ ├── Properties
│ │ └── launchSettings.json
│ │ ├── StorageEndToEndTests.cs
│ │ └── Utilities.cs
├── README.md
├── confluent_cloud_cacert.pem
├── host.json
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── microsoft
│ │ │ └── azure
│ │ │ └── functions
│ │ │ └── endtoend
│ │ │ ├── BindingNameTests.java
│ │ │ ├── BlobTriggerSdkTypesTests.java
│ │ │ ├── BlobTriggerTests.java
│ │ │ ├── HttpTriggerTests.java
│ │ │ ├── QueueTriggerTests.java
│ │ │ ├── TableTests.java
│ │ │ └── TimerTriggerTests.java
│ │ └── resources
│ │ └── logback.xml
└── utils
│ ├── Config.json
│ └── docker-compose.yml
├── endtoendtests
├── Azure.Functions.Java.Tests.E2E
│ ├── Azure.Functions.Java.Tests.E2E.sln
│ └── Azure.Functions.Java.Tests.E2E
│ │ ├── Azure.Functions.Java.Tests.E2E.csproj
│ │ ├── Constants.cs
│ │ ├── CosmosDBEndToEndTests.cs
│ │ ├── DurableEndToEndTests.cs
│ │ ├── EventGridEndToEndTests.cs
│ │ ├── EventHubsEndToEndTests.cs
│ │ ├── Fixtures
│ │ ├── FixtureHelpers.cs
│ │ └── FunctionAppFixture.cs
│ │ ├── Helpers
│ │ ├── AppInsight
│ │ │ ├── AppInsightHelper.cs
│ │ │ ├── Enums.cs
│ │ │ └── RestApiJsonSerialize.cs
│ │ ├── CosmosDBHelpers.cs
│ │ ├── EventGridHelpers.cs
│ │ ├── EventHubQueueHelpers.cs
│ │ ├── ServiceBusHelpers.cs
│ │ └── StorageHelpers.cs
│ │ ├── HttpEndToEndTests.cs
│ │ ├── KafkaEndToEndTests.cs
│ │ ├── Properties
│ │ └── launchSettings.json
│ │ ├── ServiceBusEndToEndTests.cs
│ │ ├── SqlEndToEndTests.cs
│ │ ├── StorageEndToEndTests.cs
│ │ └── Utilities.cs
├── README.md
├── confluent_cloud_cacert.pem
├── host.json
├── local.settings.json
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── microsoft
│ │ └── azure
│ │ └── functions
│ │ └── endtoend
│ │ ├── BindingNameTests.java
│ │ ├── BlobTriggerTests.java
│ │ ├── CosmosDBTriggerTests.java
│ │ ├── DurableFunctions.java
│ │ ├── EventGridTriggerTests.java
│ │ ├── EventHubTriggerTests.java
│ │ ├── HttpTriggerTests.java
│ │ ├── KafkaTriggerTests.java
│ │ ├── QueueTriggerTests.java
│ │ ├── ServiceBusQueueTriggerTests.java
│ │ ├── ServiceBusTopicTriggerTests.java
│ │ ├── SqlTriggerTests.java
│ │ ├── TableTests.java
│ │ ├── TimerTriggerTests.java
│ │ └── springcloud
│ │ ├── Config.java
│ │ └── SpringCloudHandler.java
│ └── resources
│ └── logback.xml
├── eng
└── ci
│ ├── code-mirror.yml
│ ├── integration-tests.yml
│ ├── official-build.yml
│ ├── public-build.yml
│ └── templates
│ ├── jobs
│ ├── build.yml
│ ├── run-emulated-tests-linux.yml
│ └── run-emulated-tests-windows.yml
│ └── official
│ └── jobs
│ ├── build-artifacts.yml
│ ├── run-e2e-tests-linux.yml
│ └── run-e2e-tests-windows.yml
├── installAdditionsLocally.ps1
├── installMavenPluginLocally.ps1
├── mvnBuild.bat
├── mvnBuildAdditions.bat
├── mvnBuildSkipTests.bat
├── package-pipeline.ps1
├── pom.xml
├── samples
├── dependency-injection-example
│ ├── README.md
│ ├── dagger-function
│ │ ├── README.md
│ │ ├── host.json
│ │ ├── img.png
│ │ ├── img_1.png
│ │ ├── pom.xml
│ │ └── src
│ │ │ └── main
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── azfs
│ │ │ │ ├── Function.java
│ │ │ │ ├── component
│ │ │ │ └── FunctionComponent.java
│ │ │ │ ├── dihook
│ │ │ │ └── MyFunctionInstanceInjector.java
│ │ │ │ ├── model
│ │ │ │ └── Communicator.java
│ │ │ │ └── module
│ │ │ │ └── FunctionModule.java
│ │ │ └── resources
│ │ │ └── META-INF
│ │ │ └── services
│ │ │ └── com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector
│ └── guice-function
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── host.json
│ │ ├── img.png
│ │ ├── img_2.png
│ │ ├── pom.xml
│ │ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── azfs
│ │ │ ├── BasicModule.java
│ │ │ ├── Communicator.java
│ │ │ ├── DefaultCommunicatorImpl.java
│ │ │ ├── Function.java
│ │ │ └── dihook
│ │ │ └── FunctionGuiceFactory.java
│ │ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector
└── spring-cloud-example
│ ├── .gitignore
│ ├── README.md
│ ├── pom.xml
│ └── src
│ ├── main
│ ├── java
│ │ └── example
│ │ │ ├── Application.java
│ │ │ ├── hello
│ │ │ ├── Hello.java
│ │ │ ├── HelloHandler.java
│ │ │ └── model
│ │ │ │ ├── Greeting.java
│ │ │ │ └── User.java
│ │ │ └── uppercase
│ │ │ ├── Config.java
│ │ │ ├── EchoHandler.java
│ │ │ └── UppercaseHandler.java
│ └── resources
│ │ └── host.json
│ └── test
│ └── java
│ └── example
│ └── hello
│ └── HelloTest.java
├── setup-tests-pipeline.ps1
├── src
├── main
│ ├── azure-functions-language-worker-protobuf
│ │ ├── .gitignore
│ │ ├── CODEOWNERS
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── src
│ │ │ └── proto
│ │ │ ├── FunctionRpc.proto
│ │ │ ├── identity
│ │ │ └── ClaimsIdentityRpc.proto
│ │ │ └── shared
│ │ │ └── NullableTypes.proto
│ └── java
│ │ └── com
│ │ └── microsoft
│ │ └── azure
│ │ └── functions
│ │ └── worker
│ │ ├── Application.java
│ │ ├── Constants.java
│ │ ├── IApplication.java
│ │ ├── JavaWorkerClient.java
│ │ ├── Util.java
│ │ ├── WorkerLogManager.java
│ │ ├── binding
│ │ ├── BindingData.java
│ │ ├── BindingDataStore.java
│ │ ├── BindingDefinition.java
│ │ ├── DataOperations.java
│ │ ├── DataSource.java
│ │ ├── DataTarget.java
│ │ ├── ExecutionContextDataSource.java
│ │ ├── ExecutionRetryContext.java
│ │ ├── ExecutionTraceContext.java
│ │ ├── RpcByteArrayDataSource.java
│ │ ├── RpcCollectionByteArrayDataSource.java
│ │ ├── RpcCollectionDoubleDataSource.java
│ │ ├── RpcCollectionLongDataSource.java
│ │ ├── RpcCollectionStringDataSource.java
│ │ ├── RpcEmptyDataSource.java
│ │ ├── RpcHttpDataTarget.java
│ │ ├── RpcHttpRequestDataSource.java
│ │ ├── RpcIntegerDataSource.java
│ │ ├── RpcJsonDataSource.java
│ │ ├── RpcModelBindingDataSource.java
│ │ ├── RpcRealNumberDataSource.java
│ │ ├── RpcStringDataSource.java
│ │ └── RpcUnspecifiedDataTarget.java
│ │ ├── broker
│ │ ├── CoreTypeResolver.java
│ │ ├── EnhancedJavaMethodExecutorImpl.java
│ │ ├── FunctionDefinition.java
│ │ ├── JavaFunctionBroker.java
│ │ ├── JavaMethodExecutor.java
│ │ ├── JavaMethodExecutorImpl.java
│ │ ├── JavaMethodExecutors.java
│ │ ├── JavaMethodInvokeInfo.java
│ │ ├── MethodBindInfo.java
│ │ ├── ParamBindInfo.java
│ │ └── ParameterResolver.java
│ │ ├── cache
│ │ ├── WorkerObjectCache.java
│ │ └── WorkerObjectCacheKey.java
│ │ ├── chain
│ │ ├── FunctionExecutionMiddleware.java
│ │ ├── InvocationChain.java
│ │ ├── InvocationChainFactory.java
│ │ └── SdkTypeMiddleware.java
│ │ ├── description
│ │ └── FunctionMethodDescriptor.java
│ │ ├── handler
│ │ ├── FunctionEnvironmentReloadRequestHandler.java
│ │ ├── FunctionLoadRequestHandler.java
│ │ ├── InvocationRequestHandler.java
│ │ ├── MessageHandler.java
│ │ ├── RpcLogHandler.java
│ │ ├── StartStreamHandler.java
│ │ ├── WorkerInitRequestHandler.java
│ │ ├── WorkerStatusRequestHandler.java
│ │ ├── WorkerTerminateRequestHandler.java
│ │ └── WorkerWarmupHandler.java
│ │ └── reflect
│ │ ├── ClassLoaderProvider.java
│ │ ├── DefaultClassLoaderProvider.java
│ │ ├── EnhancedClassLoaderProvider.java
│ │ └── FactoryClassLoader.java
└── test
│ ├── java
│ └── com
│ │ └── microsoft
│ │ └── azure
│ │ └── functions
│ │ └── worker
│ │ ├── UtilTest.java
│ │ ├── binding
│ │ └── tests
│ │ │ ├── RpcByteArrayDataSourceTest.java
│ │ │ ├── RpcCollectionByteArrayDataSourceTest.java
│ │ │ ├── RpcCollectionDoubleDataSourceTest.java
│ │ │ ├── RpcCollectionLongDataSourceTest.java
│ │ │ ├── RpcCollectionStringDataSourceTest.java
│ │ │ ├── RpcHttpRequestDataSourceTest.java
│ │ │ ├── RpcIntegerDataSourceTest.java
│ │ │ └── RpcStringDataSourceTest.java
│ │ ├── broker
│ │ ├── JavaFunctionBrokerTest.java
│ │ ├── ParameterResolverTest.java
│ │ └── tests
│ │ │ ├── CoreTypeResolverTest.java
│ │ │ ├── FunctionDefinitionTest.java
│ │ │ ├── FunctionDefinitionTests.java
│ │ │ ├── InvalidCustomBinding.java
│ │ │ ├── TestCustomBinding.java
│ │ │ ├── TestCustomBindingNoName.java
│ │ │ ├── TestFunctionsClass.jar
│ │ │ └── TestFunctionsClass.java
│ │ ├── functional
│ │ └── tests
│ │ │ └── SimpleParamReturnTest.java
│ │ ├── handler
│ │ └── tests
│ │ │ └── FunctionEnvironmentReloadRequestHandlerTest.java
│ │ └── test
│ │ ├── ExecutionTraceContextTest.java
│ │ └── utilities
│ │ ├── FunctionsTestBase.java
│ │ └── FunctionsTestHost.java
│ └── resources
│ └── mockito-extensions
│ └── org.mockito.plugins.MockMaker
├── tools
├── .images
│ ├── remote-config.png
│ └── worker-debug-configuration.png
├── AzureFunctionsJavaWorker.nuspec
├── README.md
└── scripts
│ ├── GetBlobStorage.ps1
│ └── UpdateBlobStorage.ps1
├── warmup-function
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── microsoft
│ └── azure
│ └── functions
│ └── warmup
│ └── java
│ ├── Function.java
│ └── HttpTrigger.java
└── worker.config.json
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### Issue describing the changes in this PR
4 |
5 | resolves #issue_for_this_pr
6 |
7 | ### Pull request checklist
8 |
9 | * [ ] My changes **do not** require documentation changes
10 | * [ ] Otherwise: Documentation issue linked to PR
11 | * [ ] My changes **should not** be added to the release notes for the next release
12 | * [ ] Otherwise: I've added my notes to `release_notes.md`
13 | * [ ] My changes **do not** need to be backported to a previous version
14 | * [ ] Otherwise: Backport tracked by issue/PR #issue_or_pr
15 | * [ ] I have added all required tests (Unit tests, E2E tests)
16 |
17 |
18 | ### Additional information
19 |
20 | Additional PR information
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/about-codeowners/
2 | # for more info about CODEOWNERS file
3 | #
4 | # It uses the same pattern rule for gitignore file
5 | # https://git-scm.com/docs/gitignore#_pattern_format
6 | #
7 |
8 | #
9 | # AZURE FUNCTIONS TEAM
10 | # For all file changes, github would automatically include the following people in the PRs.
11 | #
12 | * @vrdmr @gavin-aguiar @hallvictoria @ahmedmuhsin @swapnil-nagar
13 |
--------------------------------------------------------------------------------
/CodeQL.yml:
--------------------------------------------------------------------------------
1 | path_classifiers:
2 | generated:
3 | # Classify generated code.
4 | - extract/inst
5 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | #### Investigative information
7 |
8 | Please provide the following:
9 |
10 | - Timestamp:
11 | - Function App name:
12 | - Function name(s) (as appropriate):
13 | - Invocation ID:
14 | - Region:
15 |
16 |
19 |
20 | #### Repro steps
21 |
22 | Provide the steps required to reproduce the problem:
23 |
24 |
30 |
31 | #### Expected behavior
32 |
33 | Provide a description of the expected behavior.
34 |
35 |
40 |
41 | #### Actual behavior
42 |
43 | Provide a description of the actual behavior observed.
44 |
45 |
50 |
51 | #### Known workarounds
52 |
53 | Provide a description of any known workarounds.
54 |
55 |
60 |
61 | #### Related information
62 |
63 | Provide any related information
64 |
65 | * Programming language used
66 | * Links to source
67 | * Bindings used
68 |
95 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/annotationLib/azure-functions-java-library-2.0.1-SNAPSHOT.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/annotationLib/azure-functions-java-library-2.0.1-SNAPSHOT.jar
--------------------------------------------------------------------------------
/annotationLib/warmup-httptrigger.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/annotationLib/warmup-httptrigger.jar
--------------------------------------------------------------------------------
/azure-function-examples/local.settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "IsEncrypted": false,
3 | "Values": {
4 | "AzureWebJobsStorage": "",
5 | "FUNCTIONS_WORKER_RUNTIME": "java"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Functions.Java.Tests.E2E", "Azure.Functions.Java.Tests.E2E\Azure.Functions.Java.Tests.E2E.csproj", "{830D2261-3E35-46A6-8B52-08233D852ED0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {45378AFC-889B-4751-A494-44B73F8EA77E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Always
21 |
22 |
23 | Always
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Constants.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using System;
5 |
6 | namespace Azure.Functions.Java.Tests.E2E
7 | {
8 | public static class Constants
9 | {
10 | public static string FunctionsHostUrl = Environment.GetEnvironmentVariable("FunctionAppUrl") ?? "http://localhost:7071";
11 | public static string StorageConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
12 |
13 |
14 | //Queue tests
15 | public static string OutputBindingQueueName = "test-output-java";
16 | public static string InputBindingQueueName = "test-input-java";
17 | public static string OutputBindingQueueNamePOJO = "test-output-java-pojo";
18 | public static string InputBindingQueueNamePOJO = "test-input-java-pojo";
19 | public static string InputBindingQueueNameMetadata = "test-input-java-metadata";
20 | public static string OutputBindingQueueNameMetadata = "test-output-java-metadata";
21 | public static string TestQueueMessage = "Hello, World";
22 |
23 | //Blob tests
24 | public static string TriggerInputBindingBlobContainer = "test-triggerinput-java-new";
25 | public static string InputBindingBlobContainer = "test-input-java-new";
26 | public static string OutputBindingBlobContainer = "test-output-java-new";
27 | public static string TriggerInputBindingBlobClientSdk = "test-triggerinput-blobclient";
28 | public static string TriggerInputBindingBlobContainerClientSdk = "test-triggerinput-blobcontclient";
29 |
30 | // Xunit Fixtures and Collections
31 | public const string FunctionAppCollectionName = "FunctionAppCollection";
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Fixtures/FixtureHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.Runtime.InteropServices;
8 |
9 | namespace Azure.Functions.Java.Tests.E2E
10 | {
11 | public static class FixtureHelpers
12 | {
13 | public static Process GetFuncHostProcess(bool enableAuth = false)
14 | {
15 | var funcHostProcess = new Process();
16 | var rootDir = Path.GetFullPath(@"../../../../../..");
17 |
18 | funcHostProcess.StartInfo.UseShellExecute = false;
19 | funcHostProcess.StartInfo.RedirectStandardError = true;
20 | funcHostProcess.StartInfo.RedirectStandardOutput = true;
21 | funcHostProcess.StartInfo.CreateNoWindow = true;
22 | funcHostProcess.StartInfo.WorkingDirectory = Path.Combine(rootDir, @"emulatedtests/target/azure-functions/azure-functions-java-emulatedtests");
23 | if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
24 | {
25 | funcHostProcess.StartInfo.FileName = Path.Combine(rootDir, @"Azure.Functions.Cli/func.exe");
26 | }
27 | else
28 | {
29 | funcHostProcess.StartInfo.FileName = Path.Combine(rootDir, @"Azure.Functions.Cli/func");
30 | }
31 | funcHostProcess.StartInfo.ArgumentList.Add("start");
32 | if (enableAuth)
33 | {
34 | funcHostProcess.StartInfo.ArgumentList.Add("--enableAuth");
35 | }
36 |
37 | return funcHostProcess;
38 | }
39 |
40 | public static void StartProcessWithLogging(Process funcProcess)
41 | {
42 | funcProcess.ErrorDataReceived += (sender, e) => Console.WriteLine(e?.Data);
43 | funcProcess.OutputDataReceived += (sender, e) => Console.WriteLine(e?.Data);
44 |
45 | funcProcess.Start();
46 |
47 | funcProcess.BeginErrorReadLine();
48 | funcProcess.BeginOutputReadLine();
49 | }
50 |
51 | public static void KillExistingFuncHosts()
52 | {
53 | foreach (var func in Process.GetProcessesByName("func"))
54 | {
55 | func.Kill();
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Fixtures/FunctionAppFixture.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Diagnostics;
6 | using System.Threading;
7 | using Microsoft.Extensions.Logging;
8 | using Xunit;
9 |
10 | namespace Azure.Functions.Java.Tests.E2E
11 | {
12 | public class FunctionAppFixture : IDisposable
13 | {
14 | private readonly ILogger _logger;
15 | private bool _disposed;
16 | private Process _funcProcess;
17 |
18 | public FunctionAppFixture()
19 | {
20 | // initialize logging
21 | #pragma warning disable CS0618 // Type or member is obsolete
22 | ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
23 | #pragma warning restore CS0618 // Type or member is obsolete
24 | _logger = loggerFactory.CreateLogger();
25 |
26 | // start host via CLI if testing locally
27 | if (Constants.FunctionsHostUrl.Contains("localhost"))
28 | {
29 | // kill existing func processes
30 | _logger.LogInformation("Shutting down any running functions hosts..");
31 | FixtureHelpers.KillExistingFuncHosts();
32 |
33 | // start functions process
34 | _logger.LogInformation($"Starting functions host for {Constants.FunctionAppCollectionName}..");
35 | _funcProcess = FixtureHelpers.GetFuncHostProcess();
36 |
37 | FixtureHelpers.StartProcessWithLogging(_funcProcess);
38 |
39 | _logger.LogInformation($"Waiting for functions host to be ready...");
40 | Thread.Sleep(TimeSpan.FromSeconds(30));
41 | }
42 | }
43 |
44 | protected virtual void Dispose(bool disposing)
45 | {
46 | if (!_disposed)
47 | {
48 | if (disposing)
49 | {
50 | _logger.LogInformation("FunctionAppFixture disposing.");
51 |
52 | if (_funcProcess != null)
53 | {
54 | _logger.LogInformation($"Shutting down functions host for {Constants.FunctionAppCollectionName}");
55 | _funcProcess.Kill();
56 | _funcProcess.Dispose();
57 | }
58 | }
59 |
60 | _disposed = true;
61 | }
62 | }
63 |
64 | public void Dispose()
65 | {
66 | Dispose(true);
67 | }
68 | }
69 |
70 | [CollectionDefinition(Constants.FunctionAppCollectionName)]
71 | public class FunctionAppCollection : ICollectionFixture
72 | {
73 | // This class has no code, and is never created. Its purpose is simply
74 | // to be the place to apply [CollectionDefinition] and all the
75 | // ICollectionFixture<> interfaces.
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/emulatedtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Azure.Functions.Java.Tests.E2E": {
4 | "commandName": "Project"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/emulatedtests/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "logging": {
4 | "applicationInsights": {
5 | "samplingSettings": {
6 | "isEnabled": true,
7 | "excludedTypes": "Request"
8 | }
9 | }
10 | },
11 | "extensionBundle": {
12 | "id": "Microsoft.Azure.Functions.ExtensionBundle",
13 | "version": "[4.*, 5.0.0)"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/java/com/microsoft/azure/functions/endtoend/BindingNameTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.Optional;
6 |
7 | /**
8 | * Azure Functions with Timer trigger.
9 | */
10 | public class BindingNameTests {
11 | /**
12 | * This function will be invoked with a http request and send back the url of the request back.
13 | */
14 | @FunctionName("BindingName")
15 | public HttpResponseMessage run(
16 | @HttpTrigger(name = "req", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.ANONYMOUS, route = "BindingName/{testMessage}") HttpRequestMessage> request,
17 | @BindingName("testMessage") String route,
18 | final ExecutionContext context) {
19 | context.getLogger().info("Java HTTP trigger processed a request.");
20 | return request.createResponseBuilder(HttpStatus.OK).body(route).build();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/java/com/microsoft/azure/functions/endtoend/BlobTriggerSdkTypesTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.azure.storage.blob.BlobClient;
4 | import com.azure.storage.blob.BlobContainerClient;
5 | import com.microsoft.azure.functions.ExecutionContext;
6 | import com.microsoft.azure.functions.OutputBinding;
7 | import com.microsoft.azure.functions.annotation.*;
8 |
9 | import java.io.ByteArrayOutputStream;
10 |
11 | /**
12 | * Azure Functions with Azure Storage Blob.
13 | */
14 | public class BlobTriggerSdkTypesTests {
15 | /**
16 | * 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.
17 | */
18 | @FunctionName("BlobTriggerUsingBlobClientToBlobTest")
19 | @StorageAccount("AzureWebJobsStorage")
20 | public void BlobTriggerToBlobTest_BlobClient(
21 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinput-blobclient/{name}", dataType = "binary") BlobClient triggerBlobClient,
22 | @BindingName("name") String fileName,
23 | @BlobOutput(name = "outputBlob", path = "test-output-java-new/testfile.txt", dataType = "binary") OutputBinding outputBlob,
24 | final ExecutionContext context
25 | ) {
26 | context.getLogger().info("BlobTriggerUsingBlobClient triggered for blob: " + fileName);
27 |
28 | // Download the blob content
29 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
30 | triggerBlobClient.downloadStream(outputStream);
31 |
32 | // Set the downloaded content as output
33 | outputBlob.setValue(outputStream.toByteArray());
34 | context.getLogger().info("Uploaded blob " + fileName + " to container test-output-java-new/testfile.txt");
35 | }
36 |
37 | /**
38 | * 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.
39 | */
40 | @FunctionName("BlobTriggerUsingBlobContainerClientToBlobTest")
41 | @StorageAccount("AzureWebJobsStorage")
42 | public void BlobTriggerToBlobTest_BlobContainerClient(
43 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinput-blobcontclient/{name}", dataType = "binary") BlobContainerClient triggerBlobContainerClient,
44 | @BindingName("name") String fileName,
45 | @BlobOutput(name = "outputBlob", path = "test-output-java-new/testfile.txt", dataType = "binary") OutputBinding outputBlob,
46 | final ExecutionContext context
47 | ) {
48 | context.getLogger().info("BlobTriggerUsingBlobContainerClient triggered for blob: " + fileName);
49 |
50 | // Download the blob content
51 | BlobClient triggerBlobClient = triggerBlobContainerClient.getBlobClient(fileName);
52 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
53 | triggerBlobClient.downloadStream(outputStream);
54 |
55 | // Set the downloaded content as output
56 | outputBlob.setValue(outputStream.toByteArray());
57 | context.getLogger().info("Uploaded blob " + fileName + " to container test-output-java-new/testfile.txt");
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/java/com/microsoft/azure/functions/endtoend/BlobTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 |
5 | import com.microsoft.azure.functions.*;
6 |
7 | /**
8 | * Azure Functions with Azure Storage Blob.
9 | */
10 | public class BlobTriggerTests {
11 | /**
12 | * 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.
13 | */
14 | @FunctionName("BlobTriggerToBlobTest")
15 | @StorageAccount("AzureWebJobsStorage")
16 | public void BlobTriggerToBlobTest(
17 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinput-java-new/{name}", dataType = "binary") byte[] triggerBlob,
18 | @BindingName("name") String fileName,
19 | @BlobInput(name = "inputBlob", path = "test-input-java-new/{name}", dataType = "binary") byte[] inputBlob,
20 | @BlobOutput(name = "outputBlob", path = "test-output-java-new/{name}", dataType = "binary") OutputBinding outputBlob,
21 | final ExecutionContext context
22 | ) {
23 | context.getLogger().info("Java Blob trigger function BlobTriggerToBlobTest processed a blob.\n Name: " + fileName + "\n Size: " + triggerBlob.length + " Bytes");
24 | outputBlob.setValue(inputBlob);
25 | }
26 |
27 | /*
28 | * Verified via Unit tests. Added test here for sample code
29 | */
30 | @FunctionName("BlobTriggerPOJOTest")
31 | @StorageAccount("AzureWebJobsStorage")
32 | public void BlobTriggerPOJOTest(
33 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinputpojo-java/{name}") TestBlobData triggerBlobText,
34 | @BindingName("name") String fileName,
35 | @BlobOutput(name = "outputBlob", path = "test-outputpojo-java/{name}") OutputBinding outputBlob,
36 | final ExecutionContext context
37 | ) {
38 | context.getLogger().info("Java Blob trigger function BlobTriggerPOJOTest processed a blob.\n Name: " + fileName + "\n Content: " + triggerBlobText.blobText);
39 | outputBlob.setValue(triggerBlobText);
40 | }
41 |
42 | /*
43 | * Verified via Unit tests. Added test here for sample code
44 | */
45 | @FunctionName("BlobTriggerStringTest")
46 | @StorageAccount("AzureWebJobsStorage")
47 | public void BlobTriggerStringTest(
48 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinputstring-java/{name}") String triggerBlobText,
49 | @BindingName("name") String fileName,
50 | @BlobOutput(name = "outputBlob", path = "test-outputstring-java/{name}") OutputBinding outputBlob,
51 | final ExecutionContext context
52 | ) {
53 | context.getLogger().info("Java Blob trigger function BlobTriggerStringTest processed a blob.\n Name: " + fileName + "\n Content: " + triggerBlobText);
54 | outputBlob.setValue(triggerBlobText);
55 | }
56 |
57 | public static class TestBlobData {
58 | public String blobText;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/java/com/microsoft/azure/functions/endtoend/TableTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.*;
6 |
7 | /**
8 | * Azure Functions with Azure Storage table.
9 | */
10 | public class TableTests {
11 | /**
12 | * This function will be invoked when a new queue message is received.
13 | */
14 | @FunctionName("TableInput")
15 | public void tableInputJava(
16 | @QueueTrigger(name = "message", queueName = "mytablequeue", connection = "AzureWebJobsStorage") String message,
17 | @TableInput(name = "personEntity", tableName = "Person", rowKey = "{queueTrigger}", partitionKey = "firstPartition", connection = "AzureWebJobsStorage") String personEntity,
18 | final ExecutionContext context
19 | ) {
20 | context.getLogger().info("Java Queue trigger function processed a new message: " + message);
21 | context.getLogger().info("Java Table Input function processed a Person entity:" + personEntity);
22 | }
23 |
24 | /**
25 | * This function will be invoked when a new http request is received at the specified path.
26 | */
27 | @FunctionName("TableOutput")
28 | public void tableOutputJava(
29 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
30 | @TableOutput(name = "myOutputTable", tableName = "Person", connection = "AzureWebJobsStorage") OutputBinding myOutputTable,
31 | final ExecutionContext context
32 | ) {
33 | String httpbody = request.getBody().orElse("default");
34 | myOutputTable.setValue(new Person(httpbody + "Partition", httpbody + "Row", httpbody + "Name"));
35 | context.getLogger().info("Java Table Output function write a new entity into table Person with name: " + httpbody + "Name");
36 | }
37 |
38 | public static class Person {
39 | public String PartitionKey;
40 | public String RowKey;
41 | public String Name;
42 |
43 | public Person(String p, String r, String n) {
44 | this.PartitionKey = p;
45 | this.RowKey = r;
46 | this.Name = n;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/java/com/microsoft/azure/functions/endtoend/TimerTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.time.*;
6 |
7 | /**
8 | * Azure Functions with Timer trigger.
9 | */
10 | public class TimerTriggerTests {
11 | /**
12 | * This function will be invoked periodically according to the specified schedule.
13 | */
14 | @FunctionName("TimerTrigger")
15 | public void timerHandler(
16 | @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
17 | final ExecutionContext context
18 | ) {
19 | context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/emulatedtests/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/emulatedtests/utils/Config.json:
--------------------------------------------------------------------------------
1 | {
2 | "UserConfig": {
3 | "NamespaceConfig": [
4 | {
5 | "Type": "EventHub",
6 | "Name": "emulatorNs1",
7 | "Entities": [
8 | {
9 | "Name": "python-worker-ci-eventhub-batch",
10 | "PartitionCount": 2,
11 | "ConsumerGroups": [
12 | {
13 | "Name": "cg1"
14 | }
15 | ]
16 | },
17 | {
18 | "Name": "python-worker-ci-eventhub-batch-metadata",
19 | "PartitionCount": 2,
20 | "ConsumerGroups": [
21 | {
22 | "Name": "cg1"
23 | }
24 | ]
25 | },
26 | {
27 | "Name": "python-worker-ci-eventhub-one",
28 | "PartitionCount": 2,
29 | "ConsumerGroups": [
30 | {
31 | "Name": "cg1"
32 | }
33 | ]
34 | },
35 | {
36 | "Name": "python-worker-ci-eventhub-one-metadata",
37 | "PartitionCount": 2,
38 | "ConsumerGroups": [
39 | {
40 | "Name": "cg1"
41 | }
42 | ]
43 | }
44 | ]
45 | }
46 | ],
47 | "LoggingConfig": {
48 | "Type": "File"
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/emulatedtests/utils/docker-compose.yml:
--------------------------------------------------------------------------------
1 | name: microsoft-azure-eventhubs
2 | services:
3 | # Service for the Event Hubs Emulator
4 | emulator:
5 | container_name: "eventhubs-emulator"
6 | image: "mcr.microsoft.com/azure-messaging/eventhubs-emulator:latest"
7 | volumes:
8 | - "./Config.json:/Eventhubs_Emulator/ConfigFiles/Config.json"
9 | ports:
10 | - "5672:5672"
11 | environment:
12 | BLOB_SERVER: azurite
13 | METADATA_SERVER: azurite
14 | ACCEPT_EULA: Y
15 | depends_on:
16 | - azurite
17 | networks:
18 | eh-emulator:
19 | aliases:
20 | - "eventhubs-emulator"
21 | # Service for the Azurite Storage Emulator
22 | azurite:
23 | container_name: "azurite"
24 | image: "mcr.microsoft.com/azure-storage/azurite:latest"
25 | ports:
26 | - "10000:10000"
27 | - "10001:10001"
28 | - "10002:10002"
29 | networks:
30 | eh-emulator:
31 | aliases:
32 | - "azurite"
33 | networks:
34 | eh-emulator:
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Functions.Java.Tests.E2E", "Azure.Functions.Java.Tests.E2E\Azure.Functions.Java.Tests.E2E.csproj", "{830D2261-3E35-46A6-8B52-08233D852ED0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {830D2261-3E35-46A6-8B52-08233D852ED0}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {45378AFC-889B-4751-A494-44B73F8EA77E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Always
26 |
27 |
28 | Always
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/DurableEndToEndTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using Newtonsoft.Json.Linq;
5 | using System;
6 | using System.Net;
7 | using System.Threading.Tasks;
8 | using Xunit;
9 | using System.Threading;
10 |
11 | namespace Azure.Functions.Java.Tests.E2E
12 | {
13 | [Collection(Constants.FunctionAppCollectionName)]
14 | public class DurableEndToEndTests
15 | {
16 | private readonly FunctionAppFixture _fixture;
17 |
18 | public DurableEndToEndTests(FunctionAppFixture fixture)
19 | {
20 | _fixture = fixture;
21 | }
22 |
23 | [Fact]
24 | public async Task Durable_OrchestrationCompletes()
25 | {
26 | JObject result = await Utilities.StartOrchestration("StartOrchestration", HttpStatusCode.Created);
27 | Assert.NotNull(result);
28 |
29 | String statusUrl = result["statusQueryGetUri"].ToString();
30 |
31 | int retryCount = 15;
32 | bool success = false;
33 | while(retryCount > 0)
34 | {
35 |
36 | result = await Utilities.InvokeUri(statusUrl);
37 | string runtimeStatus = result["runtimeStatus"].ToString();
38 | Console.WriteLine($"Orchestration is {runtimeStatus}");
39 |
40 | if (runtimeStatus.Equals("Completed")) {
41 | success = true;
42 | break;
43 | }
44 |
45 | Thread.Sleep(TimeSpan.FromSeconds(1));
46 | retryCount -= 1;
47 | }
48 |
49 | Assert.True(success);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Fixtures/FixtureHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.Runtime.InteropServices;
8 |
9 | namespace Azure.Functions.Java.Tests.E2E
10 | {
11 | public static class FixtureHelpers
12 | {
13 | public static Process GetFuncHostProcess(bool enableAuth = false)
14 | {
15 | var funcHostProcess = new Process();
16 | var rootDir = Path.GetFullPath(@"../../../../../..");
17 |
18 | funcHostProcess.StartInfo.UseShellExecute = false;
19 | funcHostProcess.StartInfo.RedirectStandardError = true;
20 | funcHostProcess.StartInfo.RedirectStandardOutput = true;
21 | funcHostProcess.StartInfo.CreateNoWindow = true;
22 | funcHostProcess.StartInfo.WorkingDirectory = Path.Combine(rootDir, @"endtoendtests/target/azure-functions/azure-functions-java-endtoendtests");
23 | if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
24 | {
25 | funcHostProcess.StartInfo.FileName = Path.Combine(rootDir, @"Azure.Functions.Cli/func.exe");
26 | }
27 | else
28 | {
29 | funcHostProcess.StartInfo.FileName = Path.Combine(rootDir, @"Azure.Functions.Cli/func");
30 | }
31 | funcHostProcess.StartInfo.ArgumentList.Add("start");
32 | if (enableAuth)
33 | {
34 | funcHostProcess.StartInfo.ArgumentList.Add("--enableAuth");
35 | }
36 |
37 | return funcHostProcess;
38 | }
39 |
40 | public static void StartProcessWithLogging(Process funcProcess)
41 | {
42 | funcProcess.ErrorDataReceived += (sender, e) => Console.WriteLine(e?.Data);
43 | funcProcess.OutputDataReceived += (sender, e) => Console.WriteLine(e?.Data);
44 |
45 | funcProcess.Start();
46 |
47 | funcProcess.BeginErrorReadLine();
48 | funcProcess.BeginOutputReadLine();
49 | }
50 |
51 | public static void KillExistingFuncHosts()
52 | {
53 | foreach (var func in Process.GetProcessesByName("func"))
54 | {
55 | func.Kill();
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Fixtures/FunctionAppFixture.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Diagnostics;
6 | using System.Threading;
7 | using Microsoft.Extensions.Logging;
8 | using Xunit;
9 |
10 | namespace Azure.Functions.Java.Tests.E2E
11 | {
12 | public class FunctionAppFixture : IDisposable
13 | {
14 | private readonly ILogger _logger;
15 | private bool _disposed;
16 | private Process _funcProcess;
17 |
18 | public FunctionAppFixture()
19 | {
20 | // initialize logging
21 | #pragma warning disable CS0618 // Type or member is obsolete
22 | ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
23 | #pragma warning restore CS0618 // Type or member is obsolete
24 | _logger = loggerFactory.CreateLogger();
25 |
26 | // start host via CLI if testing locally
27 | if (Constants.FunctionsHostUrl.Contains("localhost"))
28 | {
29 | // kill existing func processes
30 | _logger.LogInformation("Shutting down any running functions hosts..");
31 | FixtureHelpers.KillExistingFuncHosts();
32 |
33 | // start functions process
34 | _logger.LogInformation($"Starting functions host for {Constants.FunctionAppCollectionName}..");
35 | _funcProcess = FixtureHelpers.GetFuncHostProcess();
36 |
37 | FixtureHelpers.StartProcessWithLogging(_funcProcess);
38 |
39 | _logger.LogInformation($"Waiting for functions host to be ready...");
40 | Thread.Sleep(TimeSpan.FromSeconds(30));
41 | }
42 | }
43 |
44 | protected virtual void Dispose(bool disposing)
45 | {
46 | if (!_disposed)
47 | {
48 | if (disposing)
49 | {
50 | _logger.LogInformation("FunctionAppFixture disposing.");
51 |
52 | if (_funcProcess != null)
53 | {
54 | _logger.LogInformation($"Shutting down functions host for {Constants.FunctionAppCollectionName}");
55 | _funcProcess.Kill();
56 | _funcProcess.Dispose();
57 | }
58 | }
59 |
60 | _disposed = true;
61 | }
62 | }
63 |
64 | public void Dispose()
65 | {
66 | Dispose(true);
67 | }
68 | }
69 |
70 | [CollectionDefinition(Constants.FunctionAppCollectionName)]
71 | public class FunctionAppCollection : ICollectionFixture
72 | {
73 | // This class has no code, and is never created. Its purpose is simply
74 | // to be the place to apply [CollectionDefinition] and all the
75 | // ICollectionFixture<> interfaces.
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Helpers/AppInsight/Enums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace E2ETestCases.Utils
6 | {
7 | // Query result types
8 | public enum QueryType
9 | { requests, dependencies, exceptions, traces, statsbeat }
10 | }
11 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Helpers/EventGridHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using Newtonsoft.Json.Linq;
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Threading.Tasks;
9 |
10 | using Microsoft.Azure.EventGrid;
11 | using Microsoft.Azure.EventGrid.Models;
12 |
13 | namespace Azure.Functions.Java.Tests.E2E.Helpers
14 | {
15 | public class EventGridHelpers
16 | {
17 | private static EventGridClient _eventGridClient;
18 |
19 | private static string topicHostname = null;
20 |
21 | public EventGridHelpers(string eventGridTopicEndpoint, string eventGridTopicKey)
22 | {
23 | TopicCredentials topicCredentials = new TopicCredentials(eventGridTopicKey);
24 | _eventGridClient = new EventGridClient(topicCredentials);
25 |
26 | topicHostname = new Uri(eventGridTopicEndpoint).Host;
27 | }
28 |
29 | public async Task SendEventAsync(string eventId, string subject,
30 | JObject data, string eventType, DateTime eventDateTime, string dataVersion)
31 | {
32 | List events = new List();
33 | var eventGridEvent = new EventGridEvent(eventId, subject, data,
34 | eventType, eventDateTime, dataVersion);
35 | events.Add(eventGridEvent);
36 |
37 | await _eventGridClient.PublishEventsAsync(topicHostname, events);
38 | }
39 |
40 | public static async Task SendEventsAsync(List eventGridEvents)
41 | {
42 | await _eventGridClient.PublishEventsAsync(topicHostname, eventGridEvents);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Helpers/EventHubQueueHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using Microsoft.Azure.EventHubs;
5 | using Newtonsoft.Json;
6 | using Newtonsoft.Json.Linq;
7 | using System.Collections.Generic;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace Azure.Functions.Java.Tests.E2E
12 | {
13 | public class EventHubQueueHelpers
14 | {
15 | public static async Task SendJSONMessagesAsync(string eventId, string connectionString)
16 | {
17 | // write 3 events
18 | List events = new List();
19 | string[] ids = new string[3];
20 | for (int i = 0; i < 3; i++)
21 | {
22 | ids[i] = eventId + $"TestEvent{i}";
23 | JObject jo = new JObject
24 | {
25 | { "value", ids[i] }
26 | };
27 | var evt = new EventData(Encoding.UTF8.GetBytes(jo.ToString(Formatting.None)));
28 | evt.Properties.Add("TestIndex", i);
29 | events.Add(evt);
30 | }
31 |
32 | EventHubsConnectionStringBuilder builder = new EventHubsConnectionStringBuilder(connectionString);
33 | builder.EntityPath = Constants.InputJsonEventHubName;
34 | EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(builder.ToString());
35 | await eventHubClient.SendAsync(events);
36 | }
37 |
38 | public static async Task SendMessagesAsync(string eventId, string evenHubName, string connectionString)
39 | {
40 | // write 3 events
41 | List events = new List();
42 | string[] ids = new string[3];
43 | for (int i = 0; i < 3; i++)
44 | {
45 | ids[i] = eventId + $"TestEvent{i}";
46 | var evt = new EventData(Encoding.UTF8.GetBytes(ids[i]));
47 | evt.Properties.Add("TestIndex", i);
48 | events.Add(evt);
49 | }
50 |
51 | EventHubsConnectionStringBuilder builder = new EventHubsConnectionStringBuilder(connectionString);
52 | builder.EntityPath = evenHubName;
53 | EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(builder.ToString());
54 | await eventHubClient.SendAsync(events);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Helpers/ServiceBusHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using Microsoft.Azure.ServiceBus;
5 | using Newtonsoft.Json;
6 | using Newtonsoft.Json.Linq;
7 | using System.Collections.Generic;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace Azure.Functions.Java.Tests.E2E
12 | {
13 | public class ServiceBusHelpers
14 | {
15 | public static async Task SendMessagesAsync(string eventId, string serviceBusName, string connectionString)
16 | {
17 | byte[] messageBody = System.Text.Encoding.ASCII.GetBytes(eventId);
18 | ServiceBusConnectionStringBuilder builder = new ServiceBusConnectionStringBuilder(connectionString);
19 | builder.EntityPath = serviceBusName;
20 | QueueClient client = new QueueClient(builder, ReceiveMode.PeekLock);
21 | await client.SendAsync(new Message(messageBody));
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/KafkaEndToEndTests.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection.Metadata;
6 | using System.Threading.Tasks;
7 | using Xunit;
8 |
9 | namespace Azure.Functions.Java.Tests.E2E
10 | {
11 | [Collection(Constants.FunctionAppCollectionName)]
12 | public class KafkaEndToEndTests
13 | {
14 | [Fact]
15 |
16 | public async Task KafkaTriggerAndOutputString_Succeeds()
17 | {
18 | string expectedEventId = Guid.NewGuid().ToString();
19 | try
20 | {
21 | // Send Message to the Kafka Cluster using Kafka Output
22 | await SetupQueue(Constants.OutputStringOneKafkaQueueName);
23 | Assert.True(await Utilities.InvokeHttpTrigger("HttpTriggerAndKafkaOutput", $"?&message={expectedEventId}", System.Net.HttpStatusCode.OK, expectedEventId));
24 | // Verify
25 | var queueMessage = await StorageHelpers.ReadFromQueue(Constants.OutputStringOneKafkaQueueName);
26 | Assert.Contains(expectedEventId, queueMessage);
27 | }
28 | finally
29 | {
30 | // Clear queue
31 | await StorageHelpers.ClearQueue(Constants.OutputStringOneKafkaQueueName);
32 | }
33 | }
34 | private static async Task SetupQueue(string queueName)
35 | {
36 | //Clear queue
37 | await StorageHelpers.ClearQueue(queueName);
38 |
39 | //Set up and trigger
40 | await StorageHelpers.CreateQueue(queueName);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Azure.Functions.Java.Tests.E2E": {
4 | "commandName": "Project"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/endtoendtests/Azure.Functions.Java.Tests.E2E/Azure.Functions.Java.Tests.E2E/SqlEndToEndTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) .NET Foundation. All rights reserved.
2 | // Licensed under the MIT License. See License.txt in the project root for license information.
3 |
4 | using Newtonsoft.Json;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Net;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Xunit;
11 |
12 | namespace Azure.Functions.Java.Tests.E2E
13 | {
14 | [Collection(Constants.FunctionAppCollectionName)]
15 | public class SqlEndToEndTests
16 | {
17 | private readonly FunctionAppFixture _fixture;
18 |
19 | public SqlEndToEndTests(FunctionAppFixture fixture)
20 | {
21 | this._fixture = fixture;
22 | }
23 |
24 | [Fact]
25 | public async Task SqlInput_Output_Succeeds()
26 | {
27 | TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
28 | int id = (int) t.TotalSeconds;
29 | var product = new Dictionary()
30 | {
31 | { "ProductId", id },
32 | { "Name", "test" },
33 | { "Cost", 100 }
34 | };
35 |
36 | var productString = JsonConvert.SerializeObject(product);
37 | // Insert row into Products table using SqlOutput
38 | Assert.True(await Utilities.InvokeHttpTriggerPost("AddProduct", productString, HttpStatusCode.OK));
39 |
40 | // Read row from Products table using SqlInput
41 | Assert.True(await Utilities.InvokeHttpTrigger("GetProducts", "/" + id.ToString(), HttpStatusCode.OK, productString));
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/endtoendtests/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "logging": {
4 | "applicationInsights": {
5 | "samplingSettings": {
6 | "isEnabled": true,
7 | "excludedTypes": "Request"
8 | }
9 | }
10 | },
11 | "extensionBundle": {
12 | "id": "Microsoft.Azure.Functions.ExtensionBundle",
13 | "version": "[4.*, 5.0.0)"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/endtoendtests/local.settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "IsEncrypted": false,
3 | "Values": {
4 | "AzureWebJobsServiceBus": "",
5 | "AzureWebJobsEventHubReceiver":"",
6 | "AzureWebJobsEventHubSender":"",
7 | "AzureWebJobsEventHubSender_2":"",
8 | "AzureWebJobsEventHubPath":"",
9 | "CosmosDBDatabaseName":"",
10 | "CosmosDBCollectionName":"",
11 | "BrokerList": "",
12 | "ConfluentCloudUsername": "",
13 | "ConfluentCloudPassword": "",
14 | "SBTopicName":"",
15 | "SBTopicSubName":"",
16 | "SBQueueName":"",
17 | "AzureWebJobsCosmosDBConnectionString":"",
18 | "AzureWebJobsEventGridOutputBindingTopicUriString": "",
19 | "AzureWebJobsEventGridOutputBindingTopicKeyString": "",
20 | "AzureWebJobsSqlConnectionString": "",
21 | "FUNCTIONS_WORKER_RUNTIME": "java"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/BindingNameTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.Optional;
6 |
7 | /**
8 | * Azure Functions with Timer trigger.
9 | */
10 | public class BindingNameTests {
11 | /**
12 | * This function will be invoked with a http request and send back the url of the request back.
13 | */
14 | @FunctionName("BindingName")
15 | public HttpResponseMessage run(
16 | @HttpTrigger(name = "req", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.ANONYMOUS, route = "BindingName/{testMessage}") HttpRequestMessage> request,
17 | @BindingName("testMessage") String route,
18 | final ExecutionContext context) {
19 | context.getLogger().info("Java HTTP trigger processed a request.");
20 | return request.createResponseBuilder(HttpStatus.OK).body(route).build();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/BlobTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 |
5 | import java.util.List;
6 | import java.util.Optional;
7 |
8 | import com.microsoft.azure.functions.*;
9 |
10 | /**
11 | * Azure Functions with Azure Storage Blob.
12 | */
13 | public class BlobTriggerTests {
14 | /**
15 | * 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.
16 | */
17 | @FunctionName("BlobTriggerToBlobTest")
18 | @StorageAccount("AzureWebJobsStorage")
19 | public void BlobTriggerToBlobTest(
20 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinput-java-new/{name}", dataType = "binary") byte[] triggerBlob,
21 | @BindingName("name") String fileName,
22 | @BlobInput(name = "inputBlob", path = "test-input-java-new/{name}", dataType = "binary") byte[] inputBlob,
23 | @BlobOutput(name = "outputBlob", path = "test-output-java-new/{name}", dataType = "binary") OutputBinding outputBlob,
24 | final ExecutionContext context
25 | ) {
26 | context.getLogger().info("Java Blob trigger function BlobTriggerToBlobTest processed a blob.\n Name: " + fileName + "\n Size: " + triggerBlob.length + " Bytes");
27 | outputBlob.setValue(inputBlob);
28 | }
29 |
30 | /*
31 | * Verified via Unit tests. Added test here for sample code
32 | */
33 | @FunctionName("BlobTriggerPOJOTest")
34 | @StorageAccount("AzureWebJobsStorage")
35 | public void BlobTriggerPOJOTest(
36 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinputpojo-java/{name}") TestBlobData triggerBlobText,
37 | @BindingName("name") String fileName,
38 | @BlobOutput(name = "outputBlob", path = "test-outputpojo-java/{name}") OutputBinding outputBlob,
39 | final ExecutionContext context
40 | ) {
41 | context.getLogger().info("Java Blob trigger function BlobTriggerPOJOTest processed a blob.\n Name: " + fileName + "\n Content: " + triggerBlobText.blobText);
42 | outputBlob.setValue(triggerBlobText);
43 | }
44 |
45 | /*
46 | * Verified via Unit tests. Added test here for sample code
47 | */
48 | @FunctionName("BlobTriggerStringTest")
49 | @StorageAccount("AzureWebJobsStorage")
50 | public void BlobTriggerStringTest(
51 | @BlobTrigger(name = "triggerBlob", path = "test-triggerinputstring-java/{name}") String triggerBlobText,
52 | @BindingName("name") String fileName,
53 | @BlobOutput(name = "outputBlob", path = "test-outputstring-java/{name}") OutputBinding outputBlob,
54 | final ExecutionContext context
55 | ) {
56 | context.getLogger().info("Java Blob trigger function BlobTriggerStringTest processed a blob.\n Name: " + fileName + "\n Content: " + triggerBlobText);
57 | outputBlob.setValue(triggerBlobText);
58 | }
59 |
60 | public static class TestBlobData {
61 | public String blobText;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/DurableFunctions.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.*;
6 |
7 | import com.microsoft.durabletask.DurableTaskClient;
8 | import com.microsoft.durabletask.OrchestrationRunner;
9 | import com.microsoft.durabletask.azurefunctions.DurableActivityTrigger;
10 | import com.microsoft.durabletask.azurefunctions.DurableClientContext;
11 | import com.microsoft.durabletask.azurefunctions.DurableClientInput;
12 | import com.microsoft.durabletask.azurefunctions.DurableOrchestrationTrigger;
13 |
14 | /**
15 | * Azure Durable Functions with HTTP trigger.
16 | */
17 | public class DurableFunctions {
18 | /**
19 | * This HTTP-triggered function starts the orchestration.
20 | */
21 | @FunctionName("StartOrchestration")
22 | public HttpResponseMessage startOrchestration(
23 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
24 | @DurableClientInput(name = "durableContext") DurableClientContext durableContext,
25 | final ExecutionContext context) {
26 | context.getLogger().info("Java HTTP trigger processed a request.");
27 |
28 | DurableTaskClient client = durableContext.getClient();
29 | String instanceId = client.scheduleNewOrchestrationInstance("Cities");
30 | context.getLogger().info("Created new Java orchestration with instance ID = " + instanceId);
31 | return durableContext.createCheckStatusResponse(request, instanceId);
32 | }
33 |
34 | /**
35 | * This is the orchestrator function. The OrchestrationRunner.loadAndRun() static
36 | * method is used to take the function input and execute the orchestrator logic.
37 | */
38 | @FunctionName("Cities")
39 | public String citiesOrchestrator(
40 | @DurableOrchestrationTrigger(name = "orchestratorRequestProtoBytes") String orchestratorRequestProtoBytes) {
41 | return OrchestrationRunner.loadAndRun(orchestratorRequestProtoBytes, ctx -> {
42 | String result = "";
43 | result += ctx.callActivity("Capitalize", "Tokyo", String.class).await() + ", ";
44 | result += ctx.callActivity("Capitalize", "London", String.class).await() + ", ";
45 | result += ctx.callActivity("Capitalize", "Seattle", String.class).await() + ", ";
46 | result += ctx.callActivity("Capitalize", "Austin", String.class).await();
47 | return result;
48 | });
49 | }
50 |
51 | /**
52 | * This is the activity function that gets invoked by the orchestration.
53 | */
54 | @FunctionName("Capitalize")
55 | public String capitalize(
56 | @DurableActivityTrigger(name = "name") String name,
57 | final ExecutionContext context) {
58 | context.getLogger().info("Capitalizing: " + name);
59 | return name.toUpperCase();
60 | }
61 | }
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/KafkaTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 |
4 | import java.util.*;
5 | import com.microsoft.azure.functions.annotation.*;
6 | import com.microsoft.azure.functions.*;
7 |
8 |
9 |
10 | import java.util.Optional;
11 |
12 | public class KafkaTriggerTests {
13 |
14 | @FunctionName("HttpTriggerAndKafkaOutput")
15 | public HttpResponseMessage HttpTriggerAndKafkaOutput(
16 | @HttpTrigger(name = "req", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
17 | @KafkaOutput(
18 | name = "httpTriggerAndKafkaOutput",
19 | topic = "ci",
20 | brokerList="%BrokerList%",
21 | username = "%ConfluentCloudUsername%",
22 | password = "%ConfluentCloudPassword%",
23 | authenticationMode = BrokerAuthenticationMode.PLAIN,
24 | sslCaLocation = "confluent_cloud_cacert.pem",
25 | protocol = BrokerProtocol.SASLSSL
26 | ) OutputBinding output,
27 | final ExecutionContext context) {
28 | String message = request.getQueryParameters().get("message");
29 | message = request.getBody().orElse(message);
30 | context.getLogger().info("Java Http trigger received Message:" + message +" messages for Kafka Output");
31 | output.setValue(message);
32 | return request.createResponseBuilder(HttpStatus.OK).body(message).build();
33 | }
34 |
35 | @FunctionName("KafkaTriggerAndKafkaOutput")
36 | public void KafkaTriggerAndKafkaOutput(
37 | @KafkaTrigger(
38 | name = "kafkaTriggerAndKafkaOutput",
39 | topic = "ci",
40 | brokerList="%BrokerList%",
41 | consumerGroup="$Default",
42 | username = "%ConfluentCloudUsername%",
43 | password = "%ConfluentCloudPassword%",
44 | authenticationMode = BrokerAuthenticationMode.PLAIN,
45 | protocol = BrokerProtocol.SASLSSL,
46 | sslCaLocation = "confluent_cloud_cacert.pem",
47 | dataType = "string"
48 | ) String message,
49 | @QueueOutput(name = "output", queueName = "test-kafka-output-cardinality-one-java", connection = "AzureWebJobsStorage") OutputBinding output,
50 | final ExecutionContext context) {
51 | context.getLogger().info("Java Kafka Output function processed a message: " + message);
52 | output.setValue(message);
53 | }
54 | }
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/ServiceBusQueueTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.*;
6 |
7 | /**
8 | * Azure Functions with Azure Service Bus Queue.
9 | */
10 | public class ServiceBusQueueTriggerTests {
11 |
12 | @FunctionName("ServiceBusQueueTrigger")
13 | public void serviceBusQueueTrigger(
14 | @ServiceBusQueueTrigger(name = "message", queueName = "SBQueueNameSingle", connection = "AzureWebJobsServiceBus") String message,
15 | @QueueOutput(name = "output", queueName = "test-servicebusqueuesingle-java", connection = "AzureWebJobsStorage") OutputBinding output,
16 | final ExecutionContext context
17 | ) {
18 | context.getLogger().info("Java Service Bus Queue trigger function processed a message: " + message);
19 | output.setValue(message);
20 | }
21 |
22 | @FunctionName("ServiceBusQueueBatchTrigger")
23 | public void serviceBusQueueBatchTrigger(
24 | @ServiceBusQueueTrigger(name = "message", queueName = "SBQueueNameBatch", connection = "AzureWebJobsServiceBus", cardinality = Cardinality.MANY, dataType = "String") String[] messages,
25 | @QueueOutput(name = "output", queueName = "test-servicebusqueuebatch-java", connection = "AzureWebJobsStorage") OutputBinding output,
26 | final ExecutionContext context
27 | ) {
28 | context.getLogger().info("Java Service Bus Queue trigger function processed a message: " + messages[0]);
29 | output.setValue(messages[0]);
30 | }
31 |
32 | /**
33 | * This function will be invoked when a http request is received. The message contents are provided as output to this function.
34 | */
35 | @FunctionName("ServiceBusQueueOutput")
36 | public void serviceBusQueueOutput(
37 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
38 | @ServiceBusQueueOutput(name = "output", queueName = "%SBQueueName%", connection = "AzureWebJobsServiceBus") OutputBinding output,
39 | final ExecutionContext context
40 | ) {
41 | String message = request.getBody().orElse("default message");
42 | output.setValue(message);
43 | context.getLogger().info("Java Service Bugs Queue output function got a message: " + message);
44 | }
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/ServiceBusTopicTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.*;
6 |
7 | /**
8 | * Azure Functions with Azure Service Bus Topic.
9 | */
10 | public class ServiceBusTopicTriggerTests {
11 |
12 | @FunctionName("ServiceBusTopicTrigger")
13 | public void serviceBusTopicTrigger(
14 | @ServiceBusTopicTrigger(name = "message", topicName = "SBTopicNameSingle", subscriptionName="SBTopicNameSingleSubName",connection = "AzureWebJobsServiceBus") String message,
15 | @QueueOutput(name = "output", queueName = "test-servicebustopicbatch-java", connection = "AzureWebJobsStorage") OutputBinding output,
16 | final ExecutionContext context
17 | ) {
18 | context.getLogger().info("Java Service Bus Topic trigger function processed a message: " + message);
19 | output.setValue(message);
20 | }
21 |
22 | @FunctionName("ServiceBusTopicBatchTrigger")
23 | public void serviceBusTopicBatchTrigger(
24 | @ServiceBusTopicTrigger(name = "message", topicName = "SBTopicNameBatch", subscriptionName="SBTopicNameBatchSubName",connection = "AzureWebJobsServiceBus", cardinality = Cardinality.MANY, dataType = "String") List messages,
25 | @QueueOutput(name = "output", queueName = "test-servicebustopicbatch-java", connection = "AzureWebJobsStorage") OutputBinding output,
26 | final ExecutionContext context
27 | ) {
28 | context.getLogger().info("Java Service Bus Topic trigger function processed a message: " + messages.get(0));
29 | output.setValue(messages.get(0));
30 | }
31 |
32 | /**
33 | * This function will be invoked when a http request is received. The message contents are provided as output to this function.
34 | */
35 | @FunctionName("ServiceBusTopicOutput")
36 | public void serviceBusTopicOutput(
37 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
38 | @ServiceBusTopicOutput(name = "message", topicName = "%SBTopicName%", subscriptionName="%SBTopicSubName%",connection = "AzureWebJobsServiceBus") OutputBinding output,
39 | final ExecutionContext context
40 | ) {
41 | String message = request.getBody().orElse("default message");
42 | output.setValue(message);
43 | context.getLogger().info("Java Service Bus Topic output function got a message: " + message);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/SqlTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.google.gson.Gson;
5 | import com.microsoft.azure.functions.*;
6 | import com.microsoft.azure.functions.HttpMethod;
7 | import com.microsoft.azure.functions.sql.annotation.CommandType;
8 | import com.microsoft.azure.functions.sql.annotation.SQLInput;
9 | import com.microsoft.azure.functions.sql.annotation.SQLOutput;
10 | import com.microsoft.azure.functions.sql.annotation.SQLTrigger;
11 |
12 | import java.io.IOException;
13 | import java.lang.reflect.Array;
14 | import java.util.*;
15 |
16 | /**
17 | * Azure Functions with Azure SQL DB.
18 | */
19 | public class SqlTriggerTests {
20 |
21 | @FunctionName("GetProducts")
22 | public HttpResponseMessage GetProducts(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
23 | HttpMethod.POST }, route = "getproducts/{productid}", authLevel = AuthorizationLevel.ANONYMOUS)
24 | HttpRequestMessage> request,
25 | @SQLInput(name = "products", commandText = "SELECT TOP 1 * FROM Products WHERE ProductId = @ProductId",
26 | commandType = CommandType.Text, parameters = "@ProductId={productid}",
27 | connectionStringSetting = "AzureWebJobsSqlConnectionString") Product[] products,
28 | final ExecutionContext context) {
29 |
30 | context.getLogger().info("Java HTTP trigger processed a request.");
31 |
32 | if (products.length != 0) {
33 | return request.createResponseBuilder(HttpStatus.OK).body(products[0].toString()).build();
34 | } else {
35 | return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
36 | .body("Did not find expected product in table Products").build();
37 | }
38 | }
39 |
40 | @FunctionName("AddProduct")
41 | public HttpResponseMessage AddProduct(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
42 | HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
43 | @SQLOutput(name = "product", commandText = "Products", connectionStringSetting = "AzureWebJobsSqlConnectionString") OutputBinding product,
44 | final ExecutionContext context) {
45 | context.getLogger().info("Java HTTP trigger processed a request.");
46 |
47 | String json = request.getBody().get();
48 | product.setValue(new Gson().fromJson(json, Product.class));
49 |
50 | return request.createResponseBuilder(HttpStatus.OK).body(product).build();
51 | }
52 |
53 | public class Product {
54 | public int ProductId;
55 | public String Name;
56 | public int Cost;
57 |
58 | public String toString() {
59 | return "{\"ProductId\":" + ProductId + ",\"Name\":\"" + Name + "\",\"Cost\":" + Cost + "}";
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/TableTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.util.*;
6 |
7 | /**
8 | * Azure Functions with Azure Storage table.
9 | */
10 | public class TableTests {
11 | /**
12 | * This function will be invoked when a new queue message is received.
13 | */
14 | @FunctionName("TableInput")
15 | public void tableInputJava(
16 | @QueueTrigger(name = "message", queueName = "mytablequeue", connection = "AzureWebJobsStorage") String message,
17 | @TableInput(name = "personEntity", tableName = "Person", rowKey = "{queueTrigger}", partitionKey = "firstPartition", connection = "AzureWebJobsStorage") String personEntity,
18 | final ExecutionContext context
19 | ) {
20 | context.getLogger().info("Java Queue trigger function processed a new message: " + message);
21 | context.getLogger().info("Java Table Input function processed a Person entity:" + personEntity);
22 | }
23 |
24 | /**
25 | * This function will be invoked when a new http request is received at the specified path.
26 | */
27 | @FunctionName("TableOutput")
28 | public void tableOutputJava(
29 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
30 | @TableOutput(name = "myOutputTable", tableName = "Person", connection = "AzureWebJobsStorage") OutputBinding myOutputTable,
31 | final ExecutionContext context
32 | ) {
33 | String httpbody = request.getBody().orElse("default");
34 | myOutputTable.setValue(new Person(httpbody + "Partition", httpbody + "Row", httpbody + "Name"));
35 | context.getLogger().info("Java Table Output function write a new entity into table Person with name: " + httpbody + "Name");
36 | }
37 |
38 | public static class Person {
39 | public String PartitionKey;
40 | public String RowKey;
41 | public String Name;
42 |
43 | public Person(String p, String r, String n) {
44 | this.PartitionKey = p;
45 | this.RowKey = r;
46 | this.Name = n;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/TimerTriggerTests.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend;
2 |
3 | import com.microsoft.azure.functions.annotation.*;
4 | import com.microsoft.azure.functions.*;
5 | import java.time.*;
6 |
7 | /**
8 | * Azure Functions with Timer trigger.
9 | */
10 | public class TimerTriggerTests {
11 | /**
12 | * This function will be invoked periodically according to the specified schedule.
13 | */
14 | @FunctionName("TimerTrigger")
15 | public void timerHandler(
16 | @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
17 | final ExecutionContext context
18 | ) {
19 | context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/springcloud/Config.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend.springcloud;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.function.json.JsonMapper;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.messaging.Message;
9 | import reactor.core.publisher.Flux;
10 | import reactor.core.publisher.Mono;
11 |
12 | import java.util.Map;
13 | import java.util.function.Function;
14 |
15 | @SpringBootApplication
16 | public class Config {
17 |
18 | public static void main(String[] args) throws Exception {
19 | SpringApplication.run(Config.class, args);
20 | }
21 |
22 | @Bean
23 | public Function echo() {
24 | return payload -> payload;
25 | }
26 |
27 | @Bean
28 | public Function, String> uppercase() {
29 | return message -> {
30 | String value = message.getPayload();
31 | ExecutionContext context = (ExecutionContext) message.getHeaders().get("executionContext");
32 | if(context != null)
33 | context.getLogger().info(new StringBuilder().append("Function: ")
34 | .append(context.getFunctionName()).append(" is uppercasing ").append(value.toString()).toString());
35 | return value.toUpperCase();
36 | };
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/java/com/microsoft/azure/functions/endtoend/springcloud/SpringCloudHandler.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.endtoend.springcloud;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 | import com.microsoft.azure.functions.HttpMethod;
5 | import com.microsoft.azure.functions.HttpRequestMessage;
6 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
7 | import com.microsoft.azure.functions.annotation.FunctionName;
8 | import com.microsoft.azure.functions.annotation.HttpTrigger;
9 |
10 | import java.util.Optional;
11 |
12 | import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
13 | import org.springframework.messaging.Message;
14 | import org.springframework.messaging.support.MessageBuilder;
15 |
16 |
17 | public class SpringCloudHandler extends FunctionInvoker, String> {
18 |
19 | @FunctionName("echo")
20 | public String echo(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
21 | HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
22 | ExecutionContext context) {
23 | context.getLogger().info("Java Spring Cloud echo function processed a request.");
24 | String query = request.getQueryParameters().get("name");
25 | query = query != null ? query : "echo";
26 | Message message = MessageBuilder.withPayload(request.getBody().orElse(query)).copyHeaders(request.getHeaders()).build();
27 | return handleRequest(message, context);
28 | }
29 |
30 | @FunctionName("uppercase")
31 | public String uppercase(
32 | @HttpTrigger(
33 | name = "req",
34 | methods = {HttpMethod.GET, HttpMethod.POST},
35 | authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
36 | ExecutionContext context
37 | ) {
38 | context.getLogger().info("Java Spring Cloud uppercase function processed a request.");
39 | String query = request.getQueryParameters().get("name");
40 | query = query != null ? query : "uppercase";
41 | Message message = MessageBuilder.withPayload(request.getBody().orElse(query))
42 | .copyHeaders(request.getHeaders()).build();
43 | return handleRequest(message, context);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/endtoendtests/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/eng/ci/code-mirror.yml:
--------------------------------------------------------------------------------
1 | trigger:
2 | branches:
3 | include:
4 | - dev
5 | - release/* # azure-functions-java-worker github repo restricts creation of release/* branches, so using a pattern is safe here.
6 |
7 | resources:
8 | repositories:
9 | - repository: eng
10 | type: git
11 | name: engineering
12 | ref: refs/tags/release
13 |
14 | variables:
15 | - template: ci/variables/cfs.yml@eng
16 |
17 | extends:
18 | template: ci/code-mirror.yml@eng
--------------------------------------------------------------------------------
/eng/ci/integration-tests.yml:
--------------------------------------------------------------------------------
1 | trigger: none # ensure this is not ran as a CI build
2 |
3 | pr:
4 | branches:
5 | include:
6 | - dev
7 | - release/*
8 |
9 | resources:
10 | repositories:
11 | - repository: 1es
12 | type: git
13 | name: 1ESPipelineTemplates/1ESPipelineTemplates
14 | ref: refs/tags/release
15 | - repository: eng
16 | type: git
17 | name: engineering
18 | ref: refs/tags/release
19 |
20 | variables:
21 | - template: ci/variables/build.yml@eng
22 | - template: /ci/variables/cfs.yml@eng
23 |
24 | extends:
25 | template: v1/1ES.Unofficial.PipelineTemplate.yml@1es
26 | parameters:
27 | pool:
28 | name: 1es-pool-azfunc
29 | image: 1es-windows-2022
30 | os: windows
31 |
32 | stages:
33 | - stage: TestWindows
34 | jobs:
35 | - template: /eng/ci/templates/official/jobs/run-e2e-tests-windows.yml@self
36 |
37 | - stage: TestLinux
38 | dependsOn:
39 | - TestWindows
40 |
41 | jobs:
42 | - template: /eng/ci/templates/official/jobs/run-e2e-tests-linux.yml@self
--------------------------------------------------------------------------------
/eng/ci/official-build.yml:
--------------------------------------------------------------------------------
1 | schedules:
2 | - cron: '0 20 * * *'
3 | displayName: Nightly Build
4 | branches:
5 | include:
6 | - dev
7 | always: true
8 |
9 | trigger:
10 | batch: true
11 | branches:
12 | include:
13 | - dev
14 | - release/* # azure-functions-java-worker github repo restricts creation of release/* branches, so using a pattern is safe here.
15 |
16 | # CI only, does not trigger on PRs.
17 | pr: none
18 |
19 | resources:
20 | repositories:
21 | - repository: 1es
22 | type: git
23 | name: 1ESPipelineTemplates/1ESPipelineTemplates
24 | ref: refs/tags/release
25 | - repository: eng
26 | type: git
27 | name: engineering
28 | ref: refs/tags/release
29 |
30 | variables:
31 | - template: ci/variables/build.yml@eng
32 | - template: ci/variables/cfs.yml@eng
33 | - name: codeql.language
34 | value: java,powershell,csharp
35 | - name: codeql.buildIdentifier
36 | value: java_worker_official
37 | - name: codeql.excludePathPatterns
38 | value: extract/inst
39 |
40 | extends:
41 | template: v1/1ES.Official.PipelineTemplate.yml@1es
42 | parameters:
43 | pool:
44 | name: 1es-pool-azfunc
45 | image: 1es-windows-2022
46 | os: windows
47 |
48 | stages:
49 | - stage: Build
50 | jobs:
51 | - template: /eng/ci/templates/official/jobs/build-artifacts.yml@self
52 |
53 | - stage: TestWindows
54 | dependsOn: []
55 | jobs:
56 | - template: /eng/ci/templates/jobs/run-emulated-tests-windows.yml@self
57 | parameters:
58 | poolName: 1es-pool-azfunc
59 |
60 | - stage: TestLinux
61 | dependsOn: []
62 | jobs:
63 | - template: /eng/ci/templates/jobs/run-emulated-tests-linux.yml@self
64 | parameters:
65 | poolName: 1es-pool-azfunc
66 |
--------------------------------------------------------------------------------
/eng/ci/public-build.yml:
--------------------------------------------------------------------------------
1 | schedules:
2 | - cron: '0 0 * * *'
3 | displayName: Nightly Build
4 | branches:
5 | include:
6 | - dev
7 | always: true
8 |
9 | trigger:
10 | batch: true
11 | branches:
12 | include:
13 | - dev
14 |
15 | pr:
16 | branches:
17 | include:
18 | - dev
19 |
20 | resources:
21 | repositories:
22 | - repository: 1es
23 | type: git
24 | name: 1ESPipelineTemplates/1ESPipelineTemplates
25 | ref: refs/tags/release
26 |
27 | parameters:
28 | - name: runSdkTypesTests
29 | type: boolean
30 | default: false
31 |
32 | extends:
33 | template: v1/1ES.Unofficial.PipelineTemplate.yml@1es
34 | parameters:
35 | pool:
36 | name: 1es-pool-azfunc-public
37 | image: 1es-windows-2022
38 | os: windows
39 |
40 | sdl:
41 | codeql:
42 | compiled:
43 | enabled: true # still only runs for default branch
44 | language: java,powershell,csharp
45 | buildIdentifier: java_worker_public
46 | excludePathPatterns: extract/inst
47 |
48 | settings:
49 | # PR's from forks do not have sufficient permissions to set tags.
50 | skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }}
51 |
52 | stages:
53 | - stage: Build
54 | jobs:
55 | - template: /eng/ci/templates/jobs/build.yml@self
56 |
57 | - stage: TestWindows
58 | dependsOn: []
59 | jobs:
60 | - template: /eng/ci/templates/jobs/run-emulated-tests-windows.yml@self
61 | parameters:
62 | poolName: 1es-pool-azfunc-public
63 | runSdkTypesTests: ${{ parameters.runSdkTypesTests }}
64 |
65 | - stage: TestLinux
66 | dependsOn: []
67 | jobs:
68 | - template: /eng/ci/templates/jobs/run-emulated-tests-linux.yml@self
69 | parameters:
70 | poolName: 1es-pool-azfunc-public
71 | runSdkTypesTests: ${{ parameters.runSdkTypesTests }}
72 |
--------------------------------------------------------------------------------
/eng/ci/templates/jobs/build.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | - job: "Build"
3 | displayName: 'Build java worker'
4 |
5 | pool:
6 | name: 1es-pool-azfunc-public
7 | image: 1es-windows-2022
8 | os: windows
9 |
10 | steps:
11 | - pwsh: |
12 | Get-Command mvn
13 | displayName: 'Check Maven is installed'
14 | - pwsh: |
15 | java -version
16 | displayName: 'Check default java version'
17 | - pwsh: |
18 | .\installAdditionsLocally.ps1
19 | displayName: 'Install java-additions locally'
20 | - pwsh: |
21 | mvn clean package
22 | displayName: 'Build java worker'
--------------------------------------------------------------------------------
/eng/ci/templates/official/jobs/build-artifacts.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | - job: "Build"
3 | displayName: 'Build java worker'
4 |
5 | templateContext:
6 | outputParentDirectory: $(Build.ArtifactStagingDirectory)
7 | outputs:
8 | - output: pipelineArtifact
9 | targetPath: $(Build.ArtifactStagingDirectory)
10 | artifactName: 'drop'
11 | - output: nuget
12 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/dev'), eq(variables['UPLOADPACKAGETOPRERELEASEFEED'], true))
13 | useDotNetTask: false
14 | packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
15 | packageParentPath: '$(Build.ArtifactStagingDirectory)'
16 | publishVstsFeed: 'e6a70c92-4128-439f-8012-382fe78d6396/f37f760c-aebd-443e-9714-ce725cd427df'
17 | nuGetFeedType: 'internal'
18 | allowPackageConflicts: true
19 |
20 | pool:
21 | name: 1es-pool-azfunc
22 | image: 1es-windows-2022
23 | os: windows
24 |
25 | variables:
26 | ${{ if contains(variables['Build.SourceBranch'], 'refs/heads/release/' ) }}:
27 | isReleaseTemp: true
28 | isRelease: $[variables.isReleaseTemp]
29 |
30 | steps:
31 | - task: NuGetToolInstaller@1
32 | inputs:
33 | checkLatest: true
34 | displayName: 'Install NuGet Tool'
35 | - pwsh: |
36 | Get-Command mvn
37 | displayName: 'Check Maven is installed'
38 | - pwsh: |
39 | java -version
40 | displayName: 'Check default java version'
41 | - pwsh: |
42 | .\installAdditionsLocally.ps1
43 | displayName: 'Install java-additions locally'
44 | - pwsh: |
45 | if ("$(isRelease)"){
46 | $buildNumber="$(Build.SourceBranchName)"
47 | Write-Host "Triggered for release."
48 | }
49 | else {
50 | $buildNumber="$(Build.BuildNumber)-v4"
51 | Write-Host "Not triggered for release. Setting package suffix to '$buildNumber'"
52 | }
53 | Write-Host "##vso[task.setvariable variable=buildNumber;isOutput=true;]$buildNumber"
54 | .\package-pipeline.ps1 -buildNumber $buildNumber
55 | name: output
56 | displayName: 'Executing build script'
57 | - task: CopyFiles@2
58 | inputs:
59 | SourceFolder: '$(Build.Repository.LocalPath)/pkg'
60 | Contents: '*.nupkg'
61 | TargetFolder: '$(Build.ArtifactStagingDirectory)'
62 | CleanTargetFolder: true
63 | displayName: 'Copying files for artifacts'
--------------------------------------------------------------------------------
/installAdditionsLocally.ps1:
--------------------------------------------------------------------------------
1 | # Variables for first repository
2 | $repoUrl1 = 'https://github.com/Azure/azure-functions-java-additions.git'
3 | $branchName1 = 'dev'
4 | $repoName1 = 'azure-functions-java-additions'
5 |
6 | # Clone the first repository
7 | git clone $repoUrl1
8 |
9 | # Change directory to the cloned repository
10 | Set-Location $repoName1
11 |
12 | # Checkout the desired branch
13 | git checkout $branchName1
14 |
15 | # Detect OS and execute build accordingly
16 | if ($IsWindows) {
17 | # Run the batch script (mvnBuild.bat)
18 | & "..\mvnBuildAdditions.bat"
19 | } else {
20 | # Extract and explicitly invoke the mvn command from mvnBuild.bat
21 | $mvnCommand = Get-Content "../mvnBuildAdditions.bat" | Where-Object { $_ -match '^mvn\s+' }
22 | if ($null -ne $mvnCommand) {
23 | # Execute the extracted mvn command explicitly as a single line
24 | bash -c "$mvnCommand"
25 | } else {
26 | Write-Error "No mvn command found in mvnBuild.bat."
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/installMavenPluginLocally.ps1:
--------------------------------------------------------------------------------
1 | # Variables for second repository
2 | $repoUrl2 = 'https://github.com/ahmedmuhsin/azure-maven-plugins.git'
3 | $branchName2 = 'sdk-types'
4 | $repoName2 = 'azure-maven-plugins'
5 |
6 | # Clone the second repository
7 | git clone $repoUrl2
8 |
9 | # Change directory to the cloned repository
10 | Set-Location $repoName2
11 |
12 | # Checkout the desired branch
13 | git checkout $branchName2
14 |
15 | # Run Maven command to build/install, skipping tests and javadoc
16 | if ($IsWindows) {
17 | & "mvn" "clean" "install" "-DskipTests" "-Dmaven.javadoc.skip=true"
18 | } else {
19 | bash -c "mvn clean install -DskipTests -Dmaven.javadoc.skip=true"
20 | }
21 |
--------------------------------------------------------------------------------
/mvnBuild.bat:
--------------------------------------------------------------------------------
1 | mvn clean package -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B
--------------------------------------------------------------------------------
/mvnBuildAdditions.bat:
--------------------------------------------------------------------------------
1 | mvn clean install -U -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B -Dgpg.skip -Dspotbugs.skip=true
--------------------------------------------------------------------------------
/mvnBuildSkipTests.bat:
--------------------------------------------------------------------------------
1 | mvn clean package -Dmaven.javadoc.skip=true -Dmaven.test.skip -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B
--------------------------------------------------------------------------------
/samples/dependency-injection-example/README.md:
--------------------------------------------------------------------------------
1 | ## Dependency Injection Examples for Azure Java Functions
2 |
3 | This rep contains examples that integrate Google Dagger2 and Google Juice with Azure Java Functions.
4 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/README.md:
--------------------------------------------------------------------------------
1 | # azure-function-guice
2 | Integration Google Dagger2 with Azure Functions
3 |
4 | Utilize [com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector](https://github.com/Azure/azure-functions-java-additions/blob/dev/azure-functions-java-spi/src/main/java/com/microsoft/azure/functions/spi/inject/FunctionInstanceInjector.java) provided by azure functions java worker to integrate Google Dagger2 framework into Azure Java Function.
5 |
6 | ## Local Setup
7 | 1. Clone the repo
8 | 2. Enter corresponding directory and run `mvn clean package` to build the project
9 | 3. Run `mvn azure-functions:run` to run the project on local.
10 | Local example:
11 |
12 | 
13 |
14 | 
15 | 4. Run `mvn azure-functions:deploy` to deploy the function app, for more info about deploy azure function java app please refer to [deploy java function app](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#deploy-the-function-project-to-azure)
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "extensionBundle": {
4 | "id": "Microsoft.Azure.Functions.ExtensionBundle",
5 | "version": "[3.*, 4.0.0)"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/samples/dependency-injection-example/dagger-function/img.png
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/samples/dependency-injection-example/dagger-function/img_1.png
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/java/com/azfs/Function.java:
--------------------------------------------------------------------------------
1 | package com.azfs;
2 |
3 | import com.azfs.model.Communicator;
4 | import com.microsoft.azure.functions.ExecutionContext;
5 | import com.microsoft.azure.functions.HttpMethod;
6 | import com.microsoft.azure.functions.HttpRequestMessage;
7 | import com.microsoft.azure.functions.HttpResponseMessage;
8 | import com.microsoft.azure.functions.HttpStatus;
9 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
10 | import com.microsoft.azure.functions.annotation.FunctionName;
11 | import com.microsoft.azure.functions.annotation.HttpTrigger;
12 |
13 | import javax.inject.Inject;
14 | import java.util.Optional;
15 |
16 | /**
17 | * Azure Functions with HTTP Trigger.
18 | */
19 | public class Function {
20 | /**
21 | * This function listens at endpoint "/api/HttpExample". Two ways to invoke it using "curl" command in bash:
22 | * 1. curl -d "HTTP Body" {your host}/api/HttpExample
23 | * 2. curl "{your host}/api/HttpExample?name=HTTP%20Query"
24 | */
25 |
26 | private final Communicator communicator;
27 |
28 | @Inject
29 | public Function(Communicator communicator) {
30 | this.communicator = communicator;
31 | }
32 |
33 | @FunctionName("HttpExample")
34 | public HttpResponseMessage run(
35 | @HttpTrigger(
36 | name = "req",
37 | methods = {HttpMethod.GET, HttpMethod.POST},
38 | authLevel = AuthorizationLevel.ANONYMOUS)
39 | HttpRequestMessage> request,
40 | final ExecutionContext context) {
41 | context.getLogger().info("Java HTTP trigger processed a request.");
42 |
43 | // Parse query parameter
44 | final String query = request.getQueryParameters().get("name");
45 | final String name = request.getBody().orElse(query);
46 |
47 | communicator.communicate(context);
48 |
49 | if (name == null) {
50 | return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
51 | } else {
52 | return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/java/com/azfs/component/FunctionComponent.java:
--------------------------------------------------------------------------------
1 | package com.azfs.component;
2 |
3 | import com.azfs.Function;
4 | import com.azfs.module.FunctionModule;
5 | import dagger.Component;
6 |
7 | @Component(modules = FunctionModule.class)
8 | public interface FunctionComponent {
9 | Function buildFunction();
10 | }
11 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/java/com/azfs/dihook/MyFunctionInstanceInjector.java:
--------------------------------------------------------------------------------
1 | package com.azfs.dihook;
2 |
3 | import com.azfs.component.DaggerFunctionComponent;
4 | import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector;
5 |
6 | public class MyFunctionInstanceInjector implements FunctionInstanceInjector {
7 | @Override
8 | public T getInstance(Class aClass) throws Exception {
9 | return (T) DaggerFunctionComponent.create().buildFunction();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/java/com/azfs/model/Communicator.java:
--------------------------------------------------------------------------------
1 | package com.azfs.model;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 |
5 | public class Communicator {
6 | private final String id;
7 |
8 | public Communicator(String id) {
9 | this.id = id;
10 | }
11 |
12 | public void communicate(ExecutionContext context){
13 | context.getLogger().info("Message sent out from injected communicator :) ");
14 | //add your own logics ...
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/java/com/azfs/module/FunctionModule.java:
--------------------------------------------------------------------------------
1 | package com.azfs.module;
2 |
3 | import com.azfs.model.Communicator;
4 | import dagger.Module;
5 | import dagger.Provides;
6 |
7 | @Module
8 | public class FunctionModule {
9 | @Provides
10 | public Communicator provideCommunicator() {
11 | return new Communicator("123");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/dagger-function/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector:
--------------------------------------------------------------------------------
1 | com.azfs.dihook.MyFunctionInstanceInjector
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/.gitignore:
--------------------------------------------------------------------------------
1 | # Build output
2 | target/
3 | *.class
4 |
5 | # Log file
6 | *.log
7 |
8 | # BlueJ files
9 | *.ctxt
10 |
11 | # Mobile Tools for Java (J2ME)
12 | .mtj.tmp/
13 |
14 | # Package Files #
15 | *.jar
16 | *.war
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # IDE
26 | .idea/
27 | *.iml
28 | .settings/
29 | .project
30 | .classpath
31 | .vscode/
32 |
33 | # macOS
34 | .DS_Store
35 |
36 | # Azure Functions
37 | local.settings.json
38 | bin/
39 | obj/
40 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/README.md:
--------------------------------------------------------------------------------
1 | # azure-function-guice
2 | Integration Google Guice with Azure Functions
3 |
4 | Utilize [com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector](https://github.com/Azure/azure-functions-java-additions/blob/dev/azure-functions-java-spi/src/main/java/com/microsoft/azure/functions/spi/inject/FunctionInstanceInjector.java) provided by azure functions java worker to integrate Google Guice framework into Azure Java Function.
5 |
6 | ## Local Setup
7 | 1. Clone the repo
8 | 2. Enter corresponding directory and run `mvn clean package` to build the project
9 | 3. Run `mvn azure-functions:run` to run the project on local.
10 | Local example:
11 |
12 | 
13 |
14 | 
15 | 4. Run `mvn azure-functions:deploy` to deploy the function app, for more info about deploy azure function java app please refer to [deploy java function app](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#deploy-the-function-project-to-azure)
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "extensionBundle": {
4 | "id": "Microsoft.Azure.Functions.ExtensionBundle",
5 | "version": "[3.*, 4.0.0)"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/samples/dependency-injection-example/guice-function/img.png
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/img_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-functions-java-worker/b0b564020b6e3a4449011e2c3eb59606554adc12/samples/dependency-injection-example/guice-function/img_2.png
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/java/com/azfs/BasicModule.java:
--------------------------------------------------------------------------------
1 | package com.azfs;
2 |
3 | import com.google.inject.AbstractModule;
4 |
5 | public class BasicModule extends AbstractModule {
6 |
7 | @Override
8 | protected void configure() {
9 | bind(Communicator.class).to(DefaultCommunicatorImpl.class);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/java/com/azfs/Communicator.java:
--------------------------------------------------------------------------------
1 | package com.azfs;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 |
5 | public interface Communicator {
6 | boolean sendMessage(ExecutionContext context);
7 | }
8 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/java/com/azfs/DefaultCommunicatorImpl.java:
--------------------------------------------------------------------------------
1 | package com.azfs;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 |
5 | public class DefaultCommunicatorImpl implements Communicator{
6 | @Override
7 | public boolean sendMessage(ExecutionContext context) {
8 | context.getLogger().info("Message sent out from injected communicator :) ");
9 | //add your own logic...
10 | return true;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/java/com/azfs/Function.java:
--------------------------------------------------------------------------------
1 | package com.azfs;
2 |
3 | import com.google.inject.Inject;
4 | import com.microsoft.azure.functions.ExecutionContext;
5 | import com.microsoft.azure.functions.HttpMethod;
6 | import com.microsoft.azure.functions.HttpRequestMessage;
7 | import com.microsoft.azure.functions.HttpResponseMessage;
8 | import com.microsoft.azure.functions.HttpStatus;
9 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
10 | import com.microsoft.azure.functions.annotation.FunctionName;
11 | import com.microsoft.azure.functions.annotation.HttpTrigger;
12 |
13 | import java.util.Optional;
14 |
15 | /**
16 | * Azure Functions with HTTP Trigger.
17 | */
18 | public class Function {
19 | /**
20 | * This function listens at endpoint "/api/HttpExample". Two ways to invoke it using "curl" command in bash:
21 | * 1. curl -d "HTTP Body" {your host}/api/HttpExample
22 | * 2. curl "{your host}/api/HttpExample?name=HTTP%20Query"
23 | */
24 |
25 | @Inject
26 | public Communicator communicator;
27 |
28 | @FunctionName("HttpExample")
29 | public HttpResponseMessage run(
30 | @HttpTrigger(
31 | name = "req",
32 | methods = {HttpMethod.GET, HttpMethod.POST},
33 | authLevel = AuthorizationLevel.ANONYMOUS)
34 | HttpRequestMessage> request,
35 | final ExecutionContext context) {
36 | context.getLogger().info("Java HTTP trigger processed a request.");
37 |
38 | // Parse query parameter
39 | final String query = request.getQueryParameters().get("name");
40 | final String name = request.getBody().orElse(query);
41 |
42 | //use the injected communicator to send out message
43 | communicator.sendMessage(context);
44 |
45 | if (name == null) {
46 | return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
47 | } else {
48 | return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/java/com/azfs/dihook/FunctionGuiceFactory.java:
--------------------------------------------------------------------------------
1 | package com.azfs.dihook;
2 |
3 | import com.google.inject.Guice;
4 | import com.azfs.BasicModule;
5 | import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector;
6 |
7 | public class FunctionGuiceFactory implements FunctionInstanceInjector {
8 | @Override
9 | public T getInstance(Class functionClass) throws Exception {
10 | return Guice.createInjector(new BasicModule()).getInstance(functionClass);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/samples/dependency-injection-example/guice-function/src/main/resources/META-INF/services/com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector:
--------------------------------------------------------------------------------
1 | com.azfs.dihook.FunctionGuiceFactory
--------------------------------------------------------------------------------
/samples/spring-cloud-example/.gitignore:
--------------------------------------------------------------------------------
1 | # Build output
2 | target/
3 | *.class
4 |
5 | # Log file
6 | *.log
7 |
8 | # BlueJ files
9 | *.ctxt
10 |
11 | # Mobile Tools for Java (J2ME)
12 | .mtj.tmp/
13 |
14 | # Package Files #
15 | *.jar
16 | *.war
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # IDE
26 | .idea/
27 | *.iml
28 | .settings/
29 | .project
30 | .classpath
31 | .vscode/
32 |
33 | # macOS
34 | .DS_Store
35 |
36 | # Azure Functions
37 | local.settings.json
38 | bin/
39 | obj/
40 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/Application.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import example.uppercase.Config;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | @SpringBootApplication
8 | public class Application {
9 | public static void main(String[] args) throws Exception {
10 | SpringApplication.run(Config.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/hello/Hello.java:
--------------------------------------------------------------------------------
1 | package example.hello;
2 |
3 | import example.hello.model.*;
4 | import org.springframework.stereotype.Component;
5 | import java.util.function.Function;
6 |
7 | @Component
8 | public class Hello implements Function {
9 |
10 | @Override
11 | public Greeting apply(User user) {
12 | return new Greeting("Hello, " + user.getName() + "!\n");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/hello/HelloHandler.java:
--------------------------------------------------------------------------------
1 | package example.hello;
2 |
3 | import com.microsoft.azure.functions.*;
4 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
5 | import com.microsoft.azure.functions.annotation.FunctionName;
6 | import com.microsoft.azure.functions.annotation.HttpTrigger;
7 | import example.hello.model.*;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.stereotype.Component;
10 |
11 | import java.util.Optional;
12 |
13 | @Component
14 | public class HelloHandler {
15 |
16 | @Autowired
17 | private Hello hello;
18 |
19 | @FunctionName("hello")
20 | public HttpResponseMessage execute(
21 | @HttpTrigger(name = "request", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
22 | ExecutionContext context) {
23 | User user = request.getBody()
24 | .filter(u -> u.getName() != null)
25 | .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world")));
26 | context.getLogger().info("Greeting user name: " + user.getName());
27 | return request
28 | .createResponseBuilder(HttpStatus.OK)
29 | .body(hello.apply(user))
30 | .header("Content-Type", "application/json")
31 | .build();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/hello/model/Greeting.java:
--------------------------------------------------------------------------------
1 | package example.hello.model;
2 |
3 | public class Greeting {
4 |
5 | private String message;
6 |
7 | public Greeting() {
8 | }
9 |
10 | public Greeting(String message) {
11 | this.message = message;
12 | }
13 |
14 | public String getMessage() {
15 | return message;
16 | }
17 |
18 | public void setMessage(String message) {
19 | this.message = message;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/hello/model/User.java:
--------------------------------------------------------------------------------
1 | package example.hello.model;
2 |
3 | public class User {
4 |
5 | private String name;
6 |
7 | public User() {
8 | }
9 |
10 | public User(String name) {
11 | this.name = name;
12 | }
13 |
14 | public String getName() {
15 | return name;
16 | }
17 |
18 | public void setName(String name) {
19 | this.name = name;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/uppercase/Config.java:
--------------------------------------------------------------------------------
1 | package example.uppercase;
2 |
3 | import java.util.Map;
4 | import java.util.function.Function;
5 |
6 | import com.microsoft.azure.functions.ExecutionContext;
7 | import org.springframework.context.annotation.Configuration;
8 | import reactor.core.publisher.Flux;
9 | import reactor.core.publisher.Mono;
10 |
11 | import org.springframework.boot.SpringApplication;
12 | import org.springframework.boot.autoconfigure.SpringBootApplication;
13 | import org.springframework.cloud.function.json.JsonMapper;
14 | import org.springframework.context.annotation.Bean;
15 | import org.springframework.messaging.Message;
16 |
17 | @Configuration
18 | public class Config {
19 |
20 | @Bean
21 | public Function echo() {
22 | return payload -> payload;
23 | }
24 |
25 | @Bean
26 | public Function uppercase() {
27 | return payload -> payload.toUpperCase();
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/uppercase/EchoHandler.java:
--------------------------------------------------------------------------------
1 | package example.uppercase;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 | import com.microsoft.azure.functions.HttpMethod;
5 | import com.microsoft.azure.functions.HttpRequestMessage;
6 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
7 | import com.microsoft.azure.functions.annotation.FunctionName;
8 | import com.microsoft.azure.functions.annotation.HttpTrigger;
9 |
10 | import java.util.Optional;
11 | import java.util.function.Function;
12 |
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
15 | import org.springframework.messaging.Message;
16 | import org.springframework.messaging.support.MessageBuilder;
17 | import org.springframework.stereotype.Component;
18 |
19 | @Component
20 | public class EchoHandler {
21 |
22 | @Autowired
23 | private Function echo;
24 |
25 | @FunctionName("echo")
26 | public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
27 | HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
28 | ExecutionContext context) {
29 | return echo.apply(request.getBody().get());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/java/example/uppercase/UppercaseHandler.java:
--------------------------------------------------------------------------------
1 | package example.uppercase;
2 |
3 | import com.microsoft.azure.functions.ExecutionContext;
4 | import com.microsoft.azure.functions.HttpMethod;
5 | import com.microsoft.azure.functions.HttpRequestMessage;
6 | import com.microsoft.azure.functions.annotation.AuthorizationLevel;
7 | import com.microsoft.azure.functions.annotation.FunctionName;
8 | import com.microsoft.azure.functions.annotation.HttpTrigger;
9 |
10 | import java.util.Optional;
11 | import java.util.function.Function;
12 |
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
15 | import org.springframework.messaging.Message;
16 | import org.springframework.messaging.support.MessageBuilder;
17 | import org.springframework.stereotype.Component;
18 |
19 | @Component
20 | public class UppercaseHandler {
21 |
22 | @Autowired
23 | private Function uppercase;
24 |
25 | @FunctionName("uppercase")
26 | public String execute(
27 | @HttpTrigger(
28 | name = "req",
29 | methods = {HttpMethod.GET, HttpMethod.POST},
30 | authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
31 | ExecutionContext context
32 | ) {
33 | context.getLogger().warning("Using Java (" + System.getProperty("java.version") + ")");
34 | return uppercase.apply(request.getBody().get());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/main/resources/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "extensionBundle": {
4 | "id": "Microsoft.Azure.Functions.ExtensionBundle",
5 | "version": "[4.*, 5.0.0)"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/samples/spring-cloud-example/src/test/java/example/hello/HelloTest.java:
--------------------------------------------------------------------------------
1 | package example.hello;
2 |
3 |
4 | import example.hello.model.Greeting;
5 | import example.hello.model.User;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static org.assertj.core.api.Assertions.assertThat;
9 |
10 |
11 | public class HelloTest {
12 |
13 | @Test
14 | public void test() {
15 | Greeting result = new Hello().apply(new User("foo"));
16 | assertThat(result.getMessage()).isEqualTo("Hello, foo!\n");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/setup-tests-pipeline.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) Microsoft. All rights reserved.
3 | # Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 | #
5 | param
6 | (
7 | [Switch]$UseCoreToolsBuildFromIntegrationTests
8 | )
9 |
10 | $FUNC_RUNTIME_VERSION = 'latest'
11 |
12 | Write-Host "Installing Core Tools globlally using npm, version: $FUNC_RUNTIME_VERSION ..."
13 |
14 | $FUNC_CLI_DIRECTORY = Join-Path $PSScriptRoot 'Azure.Functions.Cli'
15 | $InstallDir = $FUNC_CLI_DIRECTORY
16 |
17 | # 1. Clean previous install
18 | Remove-Item -Recurse -Force $InstallDir -ErrorAction Ignore
19 | New-Item -ItemType Directory -Path $InstallDir -ErrorAction Ignore
20 |
21 | # 2. Locate the global prefix and module root that npm just used
22 | $globalPrefix = (npm prefix -g | Out-String).Trim() # e.g. /usr/local or C:\Users\\AppData\Roaming\npm
23 | $globalNode = (npm root -g | Out-String).Trim() # e.g. /usr/local/lib/node_modules
24 | $moduleRoot = Join-Path $globalNode 'azure-functions-core-tools'
25 |
26 | # 3. npm install → temp folder
27 | npm install -g azure-functions-core-tools@$FUNC_RUNTIME_VERSION --unsafe-perm true --foreground-scripts --loglevel verbose
28 |
29 | # 4. Copy CLI payload into the layout required by your tests
30 | Copy-Item "$moduleRoot\bin\*" $InstallDir -Recurse -Force
31 |
32 |
33 | if (-not $UseCoreToolsBuildFromIntegrationTests.IsPresent)
34 | {
35 | Write-Host "Replacing Java worker binaries in the Core Tools..."
36 | Get-ChildItem -Path "$PSScriptRoot/target/*" -Include 'azure*' -Exclude '*shaded.jar','*tests.jar' | ForEach-Object {
37 | Copy-Item $_.FullName "$FUNC_CLI_DIRECTORY/workers/java/azure-functions-java-worker.jar" -Force -Verbose
38 | }
39 |
40 | Write-Host "Copying worker.config.json to worker directory"
41 | Copy-Item "$PSScriptRoot/worker.config.json" "$FUNC_CLI_DIRECTORY/workers/java" -Force -Verbose
42 | Write-Host "Copying worker.config.json and annotationLib to worker directory"
43 | Copy-Item "$PSScriptRoot/annotationLib" "$FUNC_CLI_DIRECTORY/workers/java" -Recurse -Verbose -Force
44 | Write-Host "Copying the unsigned Application Insights Agent to worker directory"
45 | Copy-Item "$PSScriptRoot/agent" "$FUNC_CLI_DIRECTORY/workers/java" -Recurse -Verbose -Force
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/azure-functions-language-worker-protobuf/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/about-codeowners/
2 | # for more info about CODEOWNERS file
3 | #
4 | # It uses the same pattern rule for gitignore file
5 | # https://git-scm.com/docs/gitignore#_pattern_format
6 |
7 |
8 |
9 | # AZURE FUNCTIONS TEAM
10 | # For all file changes, github would automatically
11 | # include the following people in the PRs.
12 | # Language owners should get notified of any new changes to the proto file.
13 |
14 | src/proto/FunctionRpc.proto @vrdmr @gavin-aguiar @YunchuWang @surgupta-msft @satvu @ejizba @alrod @anatolib @kaibocai @shreyas-gopalakrishna @amamounelsayed @Francisco-Gamino
15 |
--------------------------------------------------------------------------------
/src/main/azure-functions-language-worker-protobuf/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/src/main/azure-functions-language-worker-protobuf/src/proto/identity/ClaimsIdentityRpc.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | // protobuf vscode extension: https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3
3 |
4 | option java_package = "com.microsoft.azure.functions.rpc.messages";
5 |
6 | import "shared/NullableTypes.proto";
7 |
8 | // Light-weight representation of a .NET System.Security.Claims.ClaimsIdentity object.
9 | // This is the same serialization as found in EasyAuth, and needs to be kept in sync with
10 | // its ClaimsIdentitySlim definition, as seen in the WebJobs extension:
11 | // https://github.com/Azure/azure-webjobs-sdk-extensions/blob/dev/src/WebJobs.Extensions.Http/ClaimsIdentitySlim.cs
12 | message RpcClaimsIdentity {
13 | NullableString authentication_type = 1;
14 | NullableString name_claim_type = 2;
15 | NullableString role_claim_type = 3;
16 | repeated RpcClaim claims = 4;
17 | }
18 |
19 | // Light-weight representation of a .NET System.Security.Claims.Claim object.
20 | // This is the same serialization as found in EasyAuth, and needs to be kept in sync with
21 | // its ClaimSlim definition, as seen in the WebJobs extension:
22 | // https://github.com/Azure/azure-webjobs-sdk-extensions/blob/dev/src/WebJobs.Extensions.Http/ClaimSlim.cs
23 | message RpcClaim {
24 | string value = 1;
25 | string type = 2;
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/azure-functions-language-worker-protobuf/src/proto/shared/NullableTypes.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | // protobuf vscode extension: https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3
3 |
4 | option java_package = "com.microsoft.azure.functions.rpc.messages";
5 |
6 | import "google/protobuf/timestamp.proto";
7 |
8 | message NullableString {
9 | oneof string {
10 | string value = 1;
11 | }
12 | }
13 |
14 | message NullableDouble {
15 | oneof double {
16 | double value = 1;
17 | }
18 | }
19 |
20 | message NullableBool {
21 | oneof bool {
22 | bool value = 1;
23 | }
24 | }
25 |
26 | message NullableTimestamp {
27 | oneof timestamp {
28 | google.protobuf.Timestamp value = 1;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/Constants.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker;
2 |
3 | /**
4 | * The Constants file for Java language worker
5 | */
6 | public final class Constants {
7 | private Constants(){}
8 |
9 | public final static String FUNCTIONS_URI_OPTION = "functions-uri";
10 | public final static String FUNCTIONS_WORKER_ID_OPTION = "functions-worker-id";
11 | public final static String FUNCTIONS_REQUEST_ID_OPTION = "functions-request-id";
12 | public final static String FUNCTIONS_GRPC_MAX_MESSAGE_LENGTH_OPTION = "functions-grpc-max-message-length";
13 | public final static String FUNCTIONS_CONSOLE_LOG_OPTION = "functions-console-log";
14 | public final static String TRIGGER_METADATA_DOLLAR_REQUEST_KEY = "$request";
15 | public final static String JAVA_LIBRARY_DIRECTORY = "/annotationLib";
16 | public final static String JAVA_LIBRARY_ARTIFACT_ID = "azure-functions-java-library";
17 | public final static String HAS_IMPLICIT_OUTPUT_QUALIFIED_NAME = "com.microsoft.azure.functions.annotation.HasImplicitOutput";
18 | public static final String JAVA_ENABLE_OPENTELEMETRY = "JAVA_ENABLE_OPENTELEMETRY";
19 | public static final String JAVA_APPLICATIONINSIGHTS_ENABLE_TELEMETRY = "JAVA_APPLICATIONINSIGHTS_ENABLE_TELEMETRY";
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/IApplication.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker;
2 |
3 | public interface IApplication {
4 | boolean logToConsole();
5 | String getHost();
6 | int getPort();
7 | Integer getMaxMessageSize();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/Util.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker;
2 |
3 | public class Util {
4 | public static boolean isTrue(String value) {
5 | if(value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("1"))) {
6 | return true;
7 | }
8 | return false;
9 | }
10 |
11 | public static String getJavaVersion() {
12 | return String.join(" - ", System.getProperty("java.home"), System.getProperty("java.version"));
13 | }
14 | }
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/binding/BindingData.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker.binding;
2 |
3 | import org.apache.commons.lang3.*;
4 |
5 | /**
6 | * Provides the information such as the matching level of the actual value retrieved/converted from BindingDataStore.
7 | */
8 | public final class BindingData {
9 | public BindingData(Object value) {
10 | this.value = value;
11 | }
12 |
13 | Object getNullSafeValue() { return this.value; }
14 | public Object getValue() { return this.getNullSafeValue() == ObjectUtils.NULL ? null : this.getNullSafeValue(); }
15 |
16 | private final Object value;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/binding/BindingDefinition.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker.binding;
2 |
3 | import com.microsoft.azure.functions.rpc.messages.*;
4 |
5 | public final class BindingDefinition {
6 | public BindingDefinition(String name, BindingInfo info) {
7 | this.name = name;
8 | this.direction = info.getDirection();
9 | }
10 |
11 | String getName() { return this.name; }
12 | boolean isInput() { return this.direction == BindingInfo.Direction.in || this.direction == BindingInfo.Direction.inout; }
13 | boolean isOutput() { return this.direction == BindingInfo.Direction.out || this.direction == BindingInfo.Direction.inout; }
14 |
15 | private final String name;
16 | private final BindingInfo.Direction direction;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/binding/DataSource.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker.binding;
2 |
3 | import java.lang.reflect.Type;
4 | import java.lang.reflect.TypeVariable;
5 | import java.util.Map;
6 | import java.util.Optional;
7 |
8 | import org.apache.commons.lang3.ObjectUtils;
9 | import org.apache.commons.lang3.exception.ExceptionUtils;
10 | import org.apache.commons.lang3.reflect.TypeUtils;
11 |
12 | /**
13 | * Base class of all data sources. Provides basic information and logic for type
14 | * conversion. Data operation template: T (source) -> Object (value).
15 | * Thread-safety: Single thread.
16 | */
17 | abstract class DataSource {
18 | DataSource(String name, T value, DataOperations operations) {
19 | this.name = name;
20 | this.value = value;
21 | this.operations = operations;
22 | }
23 |
24 | T getValue() {
25 | return this.value;
26 | }
27 |
28 | void setValue(T value) {
29 | this.value = value;
30 | }
31 |
32 | public Optional computeByName(String name, Type target) {
33 | Optional> source = this.lookupName(name);
34 | if (!source.isPresent()) {
35 | if (target.equals(Optional.class)) {
36 | return Optional.of(new BindingData(Optional.empty()));
37 | }
38 | return Optional.empty();
39 | }
40 | Optional data;
41 | try {
42 | data = source.get().computeByType(target);
43 | return data;
44 | } catch (Exception ex) {
45 | ExceptionUtils.rethrow(ex);
46 | }
47 | return Optional.empty();
48 | }
49 |
50 | public Optional computeByType(Type target) {
51 | boolean isTargetOptional = Optional.class.equals(TypeUtils.getRawType(target, null));
52 | if (isTargetOptional) {
53 | Map, Type> typeArgs = TypeUtils.getTypeArguments(target, Optional.class);
54 | target = typeArgs.size() > 0 ? typeArgs.values().iterator().next() : Object.class;
55 | }
56 | return this.operations.apply(this.value, target).map(obj -> {
57 | if (isTargetOptional) {
58 | if (obj == ObjectUtils.NULL) {
59 | obj = null;
60 | }
61 | obj = Optional.ofNullable(obj);
62 | }
63 | return new BindingData(obj);
64 | });
65 | }
66 |
67 | protected Optional> lookupName(String name) {
68 | return Optional.ofNullable(this.name != null && this.name.equals(name) ? this : null);
69 | }
70 |
71 | private final String name;
72 | private T value;
73 | private final DataOperations operations;
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/microsoft/azure/functions/worker/binding/DataTarget.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.functions.worker.binding;
2 |
3 | import java.util.Optional;
4 |
5 | import com.microsoft.azure.functions.OutputBinding;
6 | import com.microsoft.azure.functions.rpc.messages.TypedData;
7 | import com.microsoft.azure.functions.rpc.messages.TypedData.Builder;
8 |
9 | /**
10 | * Base class of all output data sources. The type conversion logic is just the
11 | * opposite of the normal input data source. Data operation template: Object
12 | * (source) -> TypedData.Builder. Thread-safety: Single thread.
13 | */
14 | abstract class DataTarget implements OutputBinding {
15 | DataTarget(DataOperations