diff --git a/README.md b/README.md index 1790cc250..9843298af 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Azure SQL bindings for Azure Functions are supported for: - .NET functions (C# in-process) - NodeJS functions (JavaScript/TypeScript) - Python functions +- Java functions ## Table of Contents @@ -32,6 +33,7 @@ Azure SQL bindings for Azure Functions are supported for: - [.NET functions](#net-functions) - [JavaScript functions](#javascript-functions) - [Python functions](#python-functions) + - [Java functions](#java-functions) - [More Samples](#more-samples) - [Input Binding](#input-binding) - [Query String](#query-string) @@ -100,7 +102,7 @@ These steps can be done in the Terminal/CLI or with PowerShell. 1. Install [Azure Functions Core Tools](https://docs.microsoft.com/azure/azure-functions/functions-run-local) -2. Create a function app for .NET, JavaScript, TypeScript or Python. +2. Create a function app for .NET, JavaScript, TypeScript, Python, or Java. **.NET** ```bash @@ -132,6 +134,13 @@ These steps can be done in the Terminal/CLI or with PowerShell. func init --worker-runtime python ``` + **Java** + ```bash + mkdir MyApp + cd MyApp + func init --worker-runtime java + ``` + 3. Enable SQL bindings on the function app. More information can be found [in Microsoft Docs](https://docs.microsoft.com/azure/azure-functions/functions-bindings-azure-sql). **.NET:** Install the extension. @@ -167,6 +176,24 @@ These steps can be done in the Terminal/CLI or with PowerShell. "PYTHON_ISOLATE_WORKER_DEPENDENCIES": "1" ``` + **Java:** + Update the `host.json` file to the preview extension bundle. + ```json + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview", + "version": "[4.*, 5.0.0)" + } + ``` + + Add the `azure-functions-java-library-sql` dependency to the pom.xml file. + ```xml + + com.microsoft.azure.functions + azure-functions-java-library-sql + 0.1.0 + + ``` + ### Configure Function App Once you have your Function App you need to configure it for use with Azure SQL bindings for Azure Functions. @@ -502,6 +529,148 @@ Note: This tutorial requires that a SQL database is setup as shown in [Create a - Hit 'F5' to run your code. Click the link to upsert the output array values in your SQL table. Your upserted values should launch in the browser. - Congratulations! You have successfully created your first SQL output binding! Checkout [Output Binding](#Output-Binding) for more information on how to use it and explore on your own! +### Java functions + +#### Input Binding Tutorial + +Note: This tutorial requires that a SQL database is setup as shown in [Create a SQL Server](#Create-a-SQL-Server). + +- Open your app that you created in [Create a Function App](#create-a-function-app) in VSCode +- Press 'F1' and search for 'Azure Functions: Create Function' +- Choose HttpTrigger -> (Provide a package name) -> (Provide a function name) -> anonymous +- In the file that opens, replace the `public HttpResponseMessage run` block with the below code. + + ```java + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET, HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getemployees") + HttpRequestMessage> request, + @SQLInput( + commandText = "SELECT * FROM Employees", + commandType = "Text", + connectionStringSetting = "SqlConnectionString") + Employee[] employees) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(employees).build(); + } + ``` + + *In the above, "select * from Employees" is the SQL script run by the input binding. The CommandType on the line below specifies whether the first line is a query or a stored procedure. On the next line, the ConnectionStringSetting specifies that the app setting that contains the SQL connection string used to connect to the database is "SqlConnectionString." For more information on this, see the [Input Binding](#Input-Binding) section* + +- Add 'import com.microsoft.azure.functions.sql.annotation.SQLInput;' +- Create a new file and call it 'Employee.java' +- Paste the below in the file. These are the column names of our SQL table. + + ```java + package com.function.Common; + + public class Employee { + private int EmployeeId; + private String LastName; + private String FirstName; + private String Company; + private String Team; + + public Employee() { + } + + public Employee(int employeeId, String lastName, String firstName, String company, String team) { + EmployeeId = employeeId; + LastName = lastName; + FirstName = firstName; + Company = company; + Team = team; + } + + public int getEmployeeId() { + return EmployeeId; + } + + public void setEmployeeId(int employeeId) { + this.EmployeeId = employeeId; + } + + public String getLastName() { + return LastName; + } + + public void setLastName(String lastName) { + this.LastName = lastName; + } + + public String getFirstName() { + return FirstName; + } + + public void setFirstName(String firstName) { + this.FirstName = firstName; + } + + public String getCompany() { + return Company; + } + + public void setCompany(String company) { + this.Company = company; + } + + public String getTeam() { + return Team; + } + + public void setTeam(String team) { + this.Team = team; + } + } + ``` + +- Navigate back to your HttpTriggerJava file. +- Open the local.settings.json file, and in the brackets for "Values," verify there is a 'SqlConnectionString.' If not, add it. +- Hit 'F5' to run your code. This will start up the Functions Host with a local HTTP Trigger and SQL Input Binding. +- Click the link that appears in your terminal. +- You should see your database output in the browser window. +- Congratulations! You have successfully created your first SQL input binding! Checkout [Input Binding](#Input-Binding) for more information on how to use it and explore on your own! + +#### Output Binding Tutorial + +Note: This tutorial requires that a SQL database is setup as shown in [Create a SQL Server](#Create-a-SQL-Server), and that you have the 'Employee.java' class from the [Input Binding Tutorial](#Input-Binding-Tutorial). + +- Open your app in VSCode +- Press 'F1' and search for 'Azure Functions: Create Function' +- Choose HttpTrigger -> (Provide a package name) -> (Provide a function name) -> anonymous +- In the file that opens, replace the `public HttpResponseMessage run` block with the below code. + + ```java + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addemployees-array") + HttpRequestMessage> request, + @SQLOutput( + commandText = "dbo.Employees", + connectionStringSetting = "SqlConnectionString") + OutputBinding output) { + + output = new Employee[] + { + new Employee(1, "Hello", "World", "Microsoft", "Functions"), + new Employee(2, "Hi", "SQLupdate", "Microsoft", "Functions") + }; + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(output).build(); + } + ``` + + *In the above, "dbo.Employees" is the name of the table our output binding is upserting into. The line below is similar to the input binding and specifies where our SqlConnectionString is. For more information on this, see the [Output Binding](#Output-Binding) section* + +- Hit 'F5' to run your code. Click the link to upsert the output array values in your SQL table. Your upserted values should launch in the browser. +- Congratulations! You have successfully created your first SQL output binding! Checkout [Output Binding](#Output-Binding) for more information on how to use it and explore on your own! + ## More Samples ### Input Binding diff --git a/java-library/pom.xml b/java-library/pom.xml index 6bd4b7fe6..3280d69c0 100644 --- a/java-library/pom.xml +++ b/java-library/pom.xml @@ -4,7 +4,7 @@ com.microsoft.azure.functions azure-functions-java-library-sql - 0.1.0 + 0.1.0 jar diff --git a/samples/samples-java/.gitignore b/samples/samples-java/.gitignore new file mode 100644 index 000000000..4568354d0 --- /dev/null +++ b/samples/samples-java/.gitignore @@ -0,0 +1,39 @@ +# Build output +target/ +repo/ +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# IDE +.idea/ +*.iml +.settings/ +.project +.classpath + +# macOS +.DS_Store + +# Azure Functions +local.settings.json +bin/ +obj/ diff --git a/samples/samples-java/.vscode/extensions.json b/samples/samples-java/.vscode/extensions.json new file mode 100644 index 000000000..8a0255c06 --- /dev/null +++ b/samples/samples-java/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "ms-azuretools.vscode-azurefunctions", + "vscjava.vscode-java-debug" + ] +} \ No newline at end of file diff --git a/samples/samples-java/.vscode/launch.json b/samples/samples-java/.vscode/launch.json new file mode 100644 index 000000000..c071177bb --- /dev/null +++ b/samples/samples-java/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Java Functions", + "type": "java", + "request": "attach", + "hostName": "127.0.0.1", + "port": 5005, + "preLaunchTask": "func: host start" + } + ] +} \ No newline at end of file diff --git a/samples/samples-java/.vscode/settings.json b/samples/samples-java/.vscode/settings.json new file mode 100644 index 000000000..11af37150 --- /dev/null +++ b/samples/samples-java/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "azureFunctions.javaBuildTool": "maven", + "azureFunctions.deploySubpath": "target/azure-functions/samples-java-1665766173929", + "azureFunctions.projectLanguage": "Java", + "azureFunctions.projectRuntime": "~4", + "debug.internalConsoleOptions": "neverOpen", + "azureFunctions.preDeployTask": "package (functions)", + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/samples/samples-java/.vscode/tasks.json b/samples/samples-java/.vscode/tasks.json new file mode 100644 index 000000000..e983ac387 --- /dev/null +++ b/samples/samples-java/.vscode/tasks.json @@ -0,0 +1,24 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "func", + "command": "host start", + "problemMatcher": "$func-java-watch", + "isBackground": true, + "options": { + "cwd": "${workspaceFolder}/target/azure-functions/samples-java-1665766173929" + }, + "dependsOn": "package (functions)" + }, + { + "label": "package (functions)", + "command": "mvn clean package", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/samples/samples-java/host.json b/samples/samples-java/host.json new file mode 100644 index 000000000..5edd80615 --- /dev/null +++ b/samples/samples-java/host.json @@ -0,0 +1,7 @@ +{ + "version": "2.0", + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview", + "version": "[4.*, 5.0.0)" + } +} diff --git a/samples/samples-java/pom.xml b/samples/samples-java/pom.xml new file mode 100644 index 000000000..807b99489 --- /dev/null +++ b/samples/samples-java/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + + com.function + samples-java + 1.0-SNAPSHOT + jar + + Java Azure Functions with SQL Bindings + + + UTF-8 + 1.8 + 1.21.0 + 2.0.1 + samples-java-1665766173929 + + + + + com.microsoft.azure.functions + azure-functions-java-library + ${azure.functions.java.library.version} + + + + com.microsoft.azure.functions + azure-functions-java-library-sql + 0.1.0 + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.4.1 + + + + + org.junit.jupiter + junit-jupiter + 5.4.2 + test + + + + org.mockito + mockito-core + 2.23.4 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + com.microsoft.azure + azure-functions-maven-plugin + ${azure.functions.maven.plugin.version} + + + ${functionAppName} + + java-functions-group + + java-functions-app-service-plan + + + westus + + + + + + + + + windows + 8 + + + + FUNCTIONS_EXTENSION_VERSION + ~4 + + + + + + package-functions + + package + + + + + + + maven-clean-plugin + 3.1.0 + + + + obj + + + + + + + diff --git a/samples/samples-java/src/main/java/com/function/AddProduct.java b/samples/samples-java/src/main/java/com/function/AddProduct.java new file mode 100644 index 000000000..505aafd48 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProduct.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.function.Common.Product; + +import java.io.IOException; +import java.util.Optional; + +public class AddProduct { + @FunctionName("AddProduct") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproduct") + HttpRequestMessage> request, + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) throws JsonParseException, JsonMappingException, IOException { + + String json = request.getBody().get(); + ObjectMapper mapper = new ObjectMapper(); + Product p = mapper.readValue(json, Product.class); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductParams.java b/samples/samples-java/src/main/java/com/function/AddProductParams.java new file mode 100644 index 000000000..b4d3ed8c3 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductParams.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.Product; + +import java.util.Optional; + +public class AddProductParams { + @FunctionName("AddProductParams") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproduct-params") + HttpRequestMessage> request, + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) { + + Product p = new Product( + Integer.parseInt(request.getQueryParameters().get("productId")), + request.getQueryParameters().get("name"), + Integer.parseInt(request.getQueryParameters().get("cost")) + ); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductReturnValue.java b/samples/samples-java/src/main/java/com/function/AddProductReturnValue.java new file mode 100644 index 000000000..27cff96d0 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductReturnValue.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.function.Common.Product; + +import java.io.IOException; +import java.util.Optional; + +public class AddProductReturnValue { + @FunctionName("AddProductReturnValue") + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + public Product run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproduct-returnvalue") + HttpRequestMessage> request) throws JsonParseException, JsonMappingException, IOException { + + String json = request.getBody().get(); + ObjectMapper mapper = new ObjectMapper(); + Product product = mapper.readValue(json, Product.class); + + return product; + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductWithDefaultPK.java b/samples/samples-java/src/main/java/com/function/AddProductWithDefaultPK.java new file mode 100644 index 000000000..47a2e41e1 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductWithDefaultPK.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.function.Common.ProductWithDefaultPK; + +import java.io.IOException; +import java.util.Optional; + +public class AddProductWithDefaultPK { + @FunctionName("AddProductWithDefaultPK") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproductwithdefaultpk") + HttpRequestMessage> request, + @SQLOutput( + commandText = "dbo.ProductsWithDefaultPK", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) throws JsonParseException, JsonMappingException, IOException { + + String json = request.getBody().get(); + ObjectMapper mapper = new ObjectMapper(); + ProductWithDefaultPK p = mapper.readValue(json, ProductWithDefaultPK.class); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumn.java b/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumn.java new file mode 100644 index 000000000..1db900af5 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumn.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.ProductWithoutId; +import java.util.Optional; + +public class AddProductWithIdentityColumn { + @FunctionName("AddProductWithIdentityColumn") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproductwithidentitycolumn") + HttpRequestMessage> request, + @SQLOutput( + commandText = "ProductsWithIdentity", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) { + + ProductWithoutId p = new ProductWithoutId( + request.getQueryParameters().get("name"), + Integer.parseInt(request.getQueryParameters().get("cost")) + ); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumnIncluded.java b/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumnIncluded.java new file mode 100644 index 000000000..bcd244f43 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductWithIdentityColumnIncluded.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.ProductWithOptionalId; + +import java.util.Optional; + +public class AddProductWithIdentityColumnIncluded { + @FunctionName("AddProductWithIdentityColumnIncluded") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = { HttpMethod.GET }, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproductwithidentitycolumnincluded") + HttpRequestMessage> request, + @SQLOutput( + commandText = "ProductsWithIdentity", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) { + + ProductWithOptionalId p = new ProductWithOptionalId( + request.getQueryParameters().get("productId") == null ? null : Integer.parseInt(request.getQueryParameters().get("productId")), + request.getQueryParameters().get("name"), + Integer.parseInt(request.getQueryParameters().get("cost")) + ); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductWithMultiplePrimaryColumnsAndIdentity.java b/samples/samples-java/src/main/java/com/function/AddProductWithMultiplePrimaryColumnsAndIdentity.java new file mode 100644 index 000000000..88f202822 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductWithMultiplePrimaryColumnsAndIdentity.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.MultiplePrimaryKeyProductWithoutId; +import java.util.Optional; + +public class AddProductWithMultiplePrimaryColumnsAndIdentity { + @FunctionName("AddProductWithMultiplePrimaryColumnsAndIdentity") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproductwithmultipleprimarycolumnsandidentity") + HttpRequestMessage> request, + @SQLOutput( + commandText = "ProductsWithMultiplePrimaryColumnsAndIdentity", + connectionStringSetting = "SqlConnectionString") + OutputBinding product) { + + MultiplePrimaryKeyProductWithoutId p = new MultiplePrimaryKeyProductWithoutId( + Integer.parseInt(request.getQueryParameters().get("externalId")), + request.getQueryParameters().get("name"), + Integer.parseInt(request.getQueryParameters().get("cost")) + ); + product.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductsArray.java b/samples/samples-java/src/main/java/com/function/AddProductsArray.java new file mode 100644 index 000000000..0a09cbdfd --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductsArray.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.function.Common.Product; + +import java.io.IOException; +import java.util.Optional; + +public class AddProductsArray { + @FunctionName("AddProductsArray") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproducts-array") + HttpRequestMessage> request, + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + OutputBinding products) throws JsonParseException, JsonMappingException, IOException { + + String json = request.getBody().get(); + ObjectMapper mapper = new ObjectMapper(); + Product[] p = mapper.readValue(json, Product[].class); + products.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/AddProductsWithIdentityColumnArray.java b/samples/samples-java/src/main/java/com/function/AddProductsWithIdentityColumnArray.java new file mode 100644 index 000000000..394acafa0 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/AddProductsWithIdentityColumnArray.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.ProductWithoutId; + +import java.util.Optional; + +public class AddProductsWithIdentityColumnArray { + @FunctionName("AddProductsWithIdentityColumnArray") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = { HttpMethod.GET }, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "addproductswithidentitycolumnarray") HttpRequestMessage> request, + @SQLOutput( + commandText = "dbo.ProductsWithIdentity", + connectionStringSetting = "SqlConnectionString") + OutputBinding products) { + + ProductWithoutId[] p = new ProductWithoutId[] { + new ProductWithoutId("Cup", 2), + new ProductWithoutId("Glasses", 12) + }; + products.setValue(p); + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/MultiplePrimaryKeyProductWithoutId.java b/samples/samples-java/src/main/java/com/function/Common/MultiplePrimaryKeyProductWithoutId.java new file mode 100644 index 000000000..2b1ee86dc --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/MultiplePrimaryKeyProductWithoutId.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class MultiplePrimaryKeyProductWithoutId { + private int ExternalId; + private String Name; + private int Cost; + + public MultiplePrimaryKeyProductWithoutId(int externalId, String name, int cost) { + ExternalId = externalId; + Name = name; + Cost = cost; + } + + public int getExternalId() { + return ExternalId; + } + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } + + public int getCost() { + return Cost; + } + + public void setCost(int cost) { + this.Cost = cost; + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/Product.java b/samples/samples-java/src/main/java/com/function/Common/Product.java new file mode 100644 index 000000000..5990ebb49 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/Product.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class Product { + private int ProductId; + private String Name; + private int Cost; + + public Product() { + } + + public Product(int productId, String name, int cost) { + ProductId = productId; + Name = name; + Cost = cost; + } + + public int getProductId() { + return ProductId; + } + + public void setProductId(int productId) { + this.ProductId = productId; + } + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } + + public int getCost() { + return Cost; + } + + public void setCost(int cost) { + this.Cost = cost; + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/ProductName.java b/samples/samples-java/src/main/java/com/function/Common/ProductName.java new file mode 100644 index 000000000..92df6d207 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/ProductName.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class ProductName { + private String Name; + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/ProductWithDefaultPK.java b/samples/samples-java/src/main/java/com/function/Common/ProductWithDefaultPK.java new file mode 100644 index 000000000..b2c7bfdcb --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/ProductWithDefaultPK.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class ProductWithDefaultPK { + private String Name; + private int Cost; + + public ProductWithDefaultPK() { + } + + public ProductWithDefaultPK(String name, int cost) { + Name = name; + Cost = cost; + } + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } + + public int getCost() { + return Cost; + } + + public void setCost(int cost) { + this.Cost = cost; + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/ProductWithOptionalId.java b/samples/samples-java/src/main/java/com/function/Common/ProductWithOptionalId.java new file mode 100644 index 000000000..f7094f2e6 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/ProductWithOptionalId.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class ProductWithOptionalId { + private Integer ProductId; + private String Name; + private int Cost; + + public ProductWithOptionalId(Integer productId, String name, int cost) { + ProductId = productId; + Name = name; + Cost = cost; + } + + public Integer getProductId() { + return ProductId; + } + + public void setProductId(Integer productId) { + this.ProductId = productId; + } + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } + + public int getCost() { + return Cost; + } + + public void setCost(int cost) { + this.Cost = cost; + } +} diff --git a/samples/samples-java/src/main/java/com/function/Common/ProductWithoutId.java b/samples/samples-java/src/main/java/com/function/Common/ProductWithoutId.java new file mode 100644 index 000000000..f80a5c76c --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/Common/ProductWithoutId.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function.Common; + +public class ProductWithoutId { + private String Name; + private int Cost; + + public ProductWithoutId(String name, int cost) { + Name = name; + Cost = cost; + } + + public String getName() { + return Name; + } + + public void setName(String name) { + this.Name = name; + } + + public int getCost() { + return Cost; + } + + public void setCost(int cost) { + this.Cost = cost; + } +} diff --git a/samples/samples-java/src/main/java/com/function/GetProductNamesView.java b/samples/samples-java/src/main/java/com/function/GetProductNamesView.java new file mode 100644 index 000000000..c1d9795a2 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/GetProductNamesView.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.function.Common.ProductName; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLInput; + +import java.util.Optional; + +public class GetProductNamesView { + @FunctionName("GetProductNamesView") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getproduct-namesview") + HttpRequestMessage> request, + @SQLInput( + commandText = "SELECT * FROM ProductNames", + commandType = "Text", + connectionStringSetting = "SqlConnectionString") + ProductName[] products) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/GetProducts.java b/samples/samples-java/src/main/java/com/function/GetProducts.java new file mode 100644 index 000000000..b2fda185d --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/GetProducts.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.function.Common.Product; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLInput; + +import java.util.Optional; + +public class GetProducts { + @FunctionName("GetProducts") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getproducts/{cost}") + HttpRequestMessage> request, + @SQLInput( + commandText = "SELECT * FROM Products WHERE Cost = @Cost", + commandType = "Text", + parameters = "@Cost={cost}", + connectionStringSetting = "SqlConnectionString") + Product[] products) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/GetProductsNameEmpty.java b/samples/samples-java/src/main/java/com/function/GetProductsNameEmpty.java new file mode 100644 index 000000000..665d83bf5 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/GetProductsNameEmpty.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.function.Common.Product; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLInput; + +import java.util.Optional; + +public class GetProductsNameEmpty { + @FunctionName("GetProductsNameEmpty") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getproducts-nameempty/{cost}") + HttpRequestMessage> request, + @SQLInput( + commandText = "SELECT * FROM Products WHERE Cost = @Cost and Name = @Name", + commandType = "Text", + parameters = "@Cost={cost},@Name=", + connectionStringSetting = "SqlConnectionString") + Product[] products) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedure.java b/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedure.java new file mode 100644 index 000000000..6f3797e71 --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedure.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.function.Common.Product; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLInput; + +import java.util.Optional; + +public class GetProductsStoredProcedure { + @FunctionName("GetProductsStoredProcedure") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getproducts-storedprocedure/{cost}") + HttpRequestMessage> request, + @SQLInput( + commandText = "SelectProductsCost", + commandType = "StoredProcedure", + parameters = "@Cost={cost}", + connectionStringSetting = "SqlConnectionString") + Product[] products) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedureFromAppSetting.java b/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedureFromAppSetting.java new file mode 100644 index 000000000..86dc6e4df --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/GetProductsStoredProcedureFromAppSetting.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.function.Common.Product; +import com.microsoft.azure.functions.HttpMethod; +import com.microsoft.azure.functions.HttpRequestMessage; +import com.microsoft.azure.functions.HttpResponseMessage; +import com.microsoft.azure.functions.HttpStatus; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.HttpTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLInput; + +import java.util.Optional; + +public class GetProductsStoredProcedureFromAppSetting { + @FunctionName("GetProductsStoredProcedureFromAppSetting") + public HttpResponseMessage run( + @HttpTrigger( + name = "req", + methods = {HttpMethod.GET}, + authLevel = AuthorizationLevel.ANONYMOUS, + route = "getproductsbycost") + HttpRequestMessage> request, + @SQLInput( + commandText = "%Sp_SelectCost%", + commandType = "StoredProcedure", + parameters = "@Cost=%ProductCost%", + connectionStringSetting = "SqlConnectionString") + Product[] products) { + + return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(products).build(); + } +} diff --git a/samples/samples-java/src/main/java/com/function/QueueTriggerProducts.java b/samples/samples-java/src/main/java/com/function/QueueTriggerProducts.java new file mode 100644 index 000000000..9d9ac4eac --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/QueueTriggerProducts.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.QueueTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.Product; + +public class QueueTriggerProducts { + @FunctionName("QueueTriggerProducts") + public void run( + @QueueTrigger( + name = "msg", + queueName = "testqueue", + connection = "AzureWebJobsStorage") + String queueMessage, + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + OutputBinding products) { + + int totalUpserts = 100; + Product[] p = new Product[totalUpserts]; + for (int i = 0; i < totalUpserts; i++) { + p[i] = new Product(i, "test", 100); + } + + products.setValue(p); + } +} diff --git a/samples/samples-java/src/main/java/com/function/TimerTriggerProducts.java b/samples/samples-java/src/main/java/com/function/TimerTriggerProducts.java new file mode 100644 index 000000000..3394d2d0f --- /dev/null +++ b/samples/samples-java/src/main/java/com/function/TimerTriggerProducts.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.function; + +import com.microsoft.azure.functions.OutputBinding; +import com.microsoft.azure.functions.annotation.FunctionName; +import com.microsoft.azure.functions.annotation.TimerTrigger; +import com.microsoft.azure.functions.sql.annotation.SQLOutput; +import com.function.Common.Product; + +public class TimerTriggerProducts { + @FunctionName("TimerTriggerProducts") + public void run( + @TimerTrigger( + name = "keepAliveTrigger", + schedule = "*/5 * * * * *") + String timerInfo, + @SQLOutput( + commandText = "Products", + connectionStringSetting = "SqlConnectionString") + OutputBinding products) { + + int totalUpserts = 1000; + Product[] p = new Product[totalUpserts]; + for (int i = 0; i < totalUpserts; i++) { + p[i] = new Product(i, "test", 100); + } + + products.setValue(p); + } +}