├── java-func-samples ├── host.json ├── .settings │ ├── org.eclipse.jdt.apt.core.prefs │ ├── org.eclipse.m2e.core.prefs │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── .vscode │ ├── extensions.json │ ├── settings.json │ ├── launch.json │ └── tasks.json ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── damoo │ │ │ └── samples │ │ │ ├── models │ │ │ ├── HttpInputObj.java │ │ │ ├── QueueObj.java │ │ │ ├── EventObj.java │ │ │ ├── CosmosObj.java │ │ │ └── StorageTableObj.java │ │ │ ├── HttpKeyVaultFunc.java │ │ │ ├── ServiceBusConsumerFunc.java │ │ │ ├── EventGridFunc.java │ │ │ ├── BlobTriggerOutput.java │ │ │ ├── ServiceBusProducerFunc.java │ │ │ ├── HttpFunc.java │ │ │ ├── ServiceBusTopicProducerFunc.java │ │ │ ├── ServiceBusTopicConsumerFunc.java │ │ │ ├── helpers │ │ │ └── DSInstance.java │ │ │ ├── PostgresCreateJDBC.java │ │ │ ├── CosmosFunc.java │ │ │ ├── StorageTableQueueFunc.java │ │ │ ├── TimerQueueMonitorFunc.java │ │ │ └── BlobTriggeredOCR.java │ └── test │ │ └── java │ │ └── com │ │ └── damoo │ │ └── samples │ │ ├── CosmosFuncTests.java │ │ ├── FunctionTests.java │ │ ├── HttpResponseMessageMock.java │ │ ├── ServiceBusFuncTests.java │ │ └── ServiceBusFuncIntegrationTests.java ├── .gitignore ├── .project ├── extensions.csproj ├── .classpath └── pom.xml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE └── README.md /java-func-samples/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0" 3 | } 4 | -------------------------------------------------------------------------------- /java-func-samples/.settings/org.eclipse.jdt.apt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.apt.aptEnabled=false 3 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-azuretools.vscode-azurefunctions", 4 | "vscjava.vscode-java-debug" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /java-func-samples/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /java-func-samples/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-azuretools.vscode-azurefunctions", 4 | "vscjava.vscode-java-debug" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /java-func-samples/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/models/HttpInputObj.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.models; 2 | 3 | public class HttpInputObj { 4 | public String name; 5 | public String favouriteFruit; 6 | } -------------------------------------------------------------------------------- /java-func-samples/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "azureFunctions.projectRuntime": "~2", 3 | "azureFunctions.projectLanguage": "Java", 4 | "azureFunctions.deploySubpath": "target/azure-functions/damoo-java-func/", 5 | "azureFunctions.preDeployTask": "package", 6 | "debug.internalConsoleOptions": "neverOpen" 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Attach to Java Functions", 6 | "type": "java", 7 | "request": "attach", 8 | "hostName": "127.0.0.1", 9 | "port": 5005, 10 | "preLaunchTask": "func: host start" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /java-func-samples/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Attach to Java Functions", 6 | "type": "java", 7 | "request": "attach", 8 | "hostName": "127.0.0.1", 9 | "port": 5005, 10 | "preLaunchTask": "func: host start" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "azureFunctions.projectRuntime": "~2", 3 | "azureFunctions.projectLanguage": "Java", 4 | "azureFunctions.deploySubpath": "java-func-samples/target/azure-functions/damoo-java-func/", 5 | "azureFunctions.preDeployTask": "package", 6 | "debug.internalConsoleOptions": "neverOpen", 7 | "java.configuration.updateBuildConfiguration": "automatic" 8 | } 9 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/models/QueueObj.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.models; 2 | 3 | import java.util.UUID; 4 | 5 | public class QueueObj { 6 | public String id; 7 | public String name; 8 | public String favouriteFruit; 9 | 10 | public QueueObj(String name, String favouriteFruit) { 11 | this.name = name; 12 | this.favouriteFruit = favouriteFruit; 13 | } 14 | } -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/models/EventObj.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.models; 2 | 3 | import java.util.Date; 4 | import java.util.Map; 5 | 6 | public class EventObj { 7 | 8 | public String topic; 9 | public String subject; 10 | public String eventType; 11 | public Date eventTime; 12 | public String id; 13 | public String dataVersion; 14 | public String metadataVersion; 15 | public Map data; 16 | 17 | } -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/models/CosmosObj.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.models; 2 | 3 | import java.util.UUID; 4 | 5 | public class CosmosObj { 6 | public String id; 7 | public String name; 8 | public String favouriteFruit; 9 | 10 | public CosmosObj(String name, String favouriteFruit) { 11 | this.id = UUID.randomUUID().toString(); 12 | this.name = name; 13 | this.favouriteFruit = favouriteFruit; 14 | } 15 | } -------------------------------------------------------------------------------- /java-func-samples/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "func", 6 | "command": "host start", 7 | "problemMatcher": "$func-watch", 8 | "isBackground": true, 9 | "options": { 10 | "cwd": "${workspaceFolder}/target/azure-functions/damoo-java-func/" 11 | }, 12 | "dependsOn": "package" 13 | }, 14 | { 15 | "label": "package", 16 | "command": "mvn clean package", 17 | "type": "shell" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /java-func-samples/.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 | 29 | # macOS 30 | .DS_Store 31 | 32 | # Azure Functions 33 | local.settings.json 34 | bin/ 35 | obj/ 36 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "func", 6 | "command": "host start", 7 | "problemMatcher": "$func-watch", 8 | "isBackground": true, 9 | "options": { 10 | "cwd": "${workspaceFolder}/java-func-samples/target/azure-functions/damoo-java-func/" 11 | }, 12 | "dependsOn": "package" 13 | }, 14 | { 15 | "label": "package", 16 | "command": "mvn clean package", 17 | "type": "shell", 18 | "options": { 19 | "cwd": "${workspaceFolder}/java-func-samples" 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /java-func-samples/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.methodParameters=generate 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.compliance=1.8 5 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 6 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 7 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 8 | org.eclipse.jdt.core.compiler.processAnnotations=disabled 9 | org.eclipse.jdt.core.compiler.release=disabled 10 | org.eclipse.jdt.core.compiler.source=1.8 11 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/models/StorageTableObj.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.models; 2 | 3 | import java.util.UUID; 4 | 5 | public class StorageTableObj { 6 | public String rowKey; 7 | public String partitionKey; 8 | public String id; 9 | public String name; 10 | public String favouriteFruit; 11 | 12 | public StorageTableObj(String rowKey, String partitionKey, String name, String favouriteFruit) { 13 | this.name = name; 14 | this.favouriteFruit = favouriteFruit; 15 | this.rowKey = rowKey; 16 | this.partitionKey = partitionKey; 17 | } 18 | } -------------------------------------------------------------------------------- /java-func-samples/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | java-func-samples 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /java-func-samples/extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | ** 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/HttpKeyVaultFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import java.util.*; 4 | import com.microsoft.azure.functions.annotation.*; 5 | import com.microsoft.azure.functions.*; 6 | 7 | /** 8 | * Azure Functions with HTTP Trigger, getting value from Key Vault 9 | */ 10 | public class HttpKeyVaultFunc { 11 | /** 12 | * New Key Vault 'binding' test 13 | */ 14 | @FunctionName("HttpKeyVaultFunc") 15 | public HttpResponseMessage run( 16 | @HttpTrigger(name = "req", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, 17 | final ExecutionContext context) { 18 | 19 | // using the key vault binding stuff in preview 20 | String secret = System.getenv("MyKVSecret"); 21 | 22 | return request.createResponseBuilder(HttpStatus.OK).body(secret).build(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/ServiceBusConsumerFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | import com.damoo.samples.models.QueueObj; 5 | import com.microsoft.azure.functions.*; 6 | 7 | /** 8 | * Azure Functions with Service Bus Trigger. 9 | */ 10 | public class ServiceBusConsumerFunc { 11 | /** 12 | * This function will be invoked when a new message is received at the Service Bus Queue. 13 | * Message is copied to secondary SB Queue 14 | */ 15 | @FunctionName("ServiceBusConsumerFunc") 16 | public void run( 17 | @ServiceBusQueueTrigger(name = "inMessage", queueName = "%SBInputQueue%", connection = "ServiceBusConStr") QueueObj inMessage, 18 | @ServiceBusQueueOutput(name = "outMessage", queueName = "%SBOutputQueue%", connection = "ServiceBusConStr") OutputBinding outMessage, 19 | final ExecutionContext context 20 | ) { 21 | outMessage.setValue(inMessage); 22 | 23 | context.getLogger().info("Java Service Bus Queue trigger function executed."); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Moore 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 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/EventGridFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | 5 | import com.damoo.samples.models.EventObj; 6 | import com.microsoft.azure.functions.*; 7 | 8 | /** 9 | * Azure Functions with Event Grid Trigger. 10 | */ 11 | public class EventGridFunc { 12 | /** 13 | * Functions fired from event grid, dumps output to Cosmos DB collection 14 | */ 15 | @FunctionName("EventGridFunc") 16 | public void run( 17 | @EventGridTrigger(dataType = "", name = "evt") EventObj evt, 18 | @CosmosDBOutput( 19 | name = "cosmosOutput", 20 | connectionStringSetting = "CosmosConStr", 21 | createIfNotExists = true, 22 | databaseName = "%DatabaseName%", 23 | collectionName = "%EventsCollectionName%" 24 | ) OutputBinding outputObj, 25 | final ExecutionContext context 26 | ) { 27 | 28 | outputObj.setValue(evt); 29 | 30 | context.getLogger().info(evt.topic); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/BlobTriggerOutput.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | import com.microsoft.azure.functions.*; 5 | 6 | /** 7 | * Azure Function with Azure Blob trigger and blob output 8 | */ 9 | public class BlobTriggerOutput { 10 | /** 11 | * 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. 12 | * Input blob gets copied to output blob 13 | */ 14 | @FunctionName("BlobTriggerOutput") 15 | @StorageAccount("StorageAccount") 16 | public void run( 17 | @BlobTrigger(name = "input", path = "dump1/{name}", dataType = "binary") byte[] inContent, 18 | @BlobOutput(name = "output", path = "dump2/{name}", dataType = "binary") OutputBinding outContent, 19 | @BindingName("name") String name, 20 | final ExecutionContext context 21 | ) { 22 | outContent.setValue(inContent); 23 | 24 | context.getLogger().info("Java Blob trigger function processed a blob. Name: " + name + "\n Size: " + inContent.length + " Bytes"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/ServiceBusProducerFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | 5 | import java.util.Optional; 6 | 7 | import com.damoo.samples.models.QueueObj; 8 | import com.microsoft.azure.functions.*; 9 | 10 | /** 11 | * Azure Functions with Http Trigger, pushing to Service Bus 12 | */ 13 | public class ServiceBusProducerFunc { 14 | /** 15 | * Accepts a custom object from the http post and pushes to Service Bus 16 | */ 17 | @FunctionName("ServiceBusProducerFunc") 18 | public void run( 19 | @HttpTrigger(name = "request", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, 20 | @ServiceBusQueueOutput(name = "msg", queueName = "%SBInputQueue%", connection = "ServiceBusConStr") OutputBinding message, 21 | final ExecutionContext context 22 | ) { 23 | 24 | Optional r = request.getBody(); 25 | message.setValue(r.get()); 26 | 27 | context.getLogger().info("Java Service Bus Queue trigger function executed."); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/HttpFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import java.util.*; 4 | import com.microsoft.azure.functions.annotation.*; 5 | import com.microsoft.azure.functions.*; 6 | 7 | /** 8 | * Azure Functions with HTTP Trigger. 9 | */ 10 | public class HttpFunc { 11 | /** 12 | * Boiler plate code from template 13 | */ 14 | @FunctionName("HttpFunc") 15 | public HttpResponseMessage run( 16 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, 17 | final ExecutionContext context) { 18 | context.getLogger().info("Java HTTP trigger processed a request."); 19 | 20 | // Parse query parameter 21 | String query = request.getQueryParameters().get("name"); 22 | String name = request.getBody().orElse(query); 23 | 24 | if (name == null) { 25 | return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build(); 26 | } else { 27 | return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/ServiceBusTopicProducerFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | 5 | import java.util.Optional; 6 | 7 | import com.damoo.samples.models.QueueObj; 8 | import com.microsoft.azure.functions.*; 9 | 10 | /** 11 | * Azure Functions with Service Topic Trigger. 12 | */ 13 | public class ServiceBusTopicProducerFunc { 14 | /** 15 | * This function will be invoked when a new message is received at the Service Bus Topic. 16 | */ 17 | @FunctionName("ServiceBusTopicProducerFunc") 18 | public void run( 19 | @HttpTrigger(name = "request", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, 20 | @ServiceBusTopicOutput( 21 | name = "queueMessage", 22 | topicName = "inTopic", 23 | subscriptionName = "inSub", 24 | connection = "ServiceBusConStr" 25 | ) 26 | OutputBinding queueMessage, 27 | final ExecutionContext context 28 | ) { 29 | 30 | queueMessage.setValue(request.getBody().get()); 31 | 32 | context.getLogger().info("Java Service Bus Topic trigger function executed."); 33 | } 34 | } -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/ServiceBusTopicConsumerFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | import com.damoo.samples.models.QueueObj; 5 | import com.microsoft.azure.functions.*; 6 | 7 | /** 8 | * Azure Functions with Service Topic Trigger. 9 | */ 10 | public class ServiceBusTopicConsumerFunc { 11 | /** 12 | * This function will be invoked when a new message is received at the Service Bus Topic. 13 | */ 14 | @FunctionName("ServiceBusTopicConsumerFunc") 15 | public void run( 16 | @ServiceBusTopicTrigger( 17 | name = "inMessage", 18 | topicName = "inTopic", 19 | subscriptionName = "inSub", 20 | connection = "ServiceBusConStr" 21 | ) 22 | QueueObj inObj, 23 | @ServiceBusTopicOutput( 24 | name = "outMessage", 25 | topicName = "outTopic", 26 | subscriptionName = "outSub", 27 | connection = "ServiceBusConStr" 28 | ) 29 | OutputBinding outObj, 30 | final ExecutionContext context 31 | ) { 32 | 33 | outObj.setValue(inObj); 34 | 35 | context.getLogger().info("Java Service Bus Topic trigger function executed."); 36 | } 37 | } -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/helpers/DSInstance.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples.helpers; 2 | 3 | import com.zaxxer.hikari.HikariConfig; 4 | import com.zaxxer.hikari.HikariDataSource; 5 | 6 | public class DSInstance { 7 | 8 | private static HikariDataSource ds = null; 9 | private static final Object lock = new Object(); 10 | 11 | private DSInstance(){} 12 | 13 | public static HikariDataSource GetDS(){ 14 | if(ds == null){ 15 | synchronized (lock){ 16 | if(ds == null){ 17 | String jdbcUrl = System.getenv("JDBCUrl"); 18 | String dbUsername = System.getenv("DBUsername"); 19 | String dbPassword = System.getenv("DBPassword"); 20 | HikariConfig config = new HikariConfig(); 21 | config.setJdbcUrl(jdbcUrl); 22 | config.setUsername(dbUsername); 23 | config.setPassword(dbPassword); 24 | config.addDataSourceProperty("cachePrepStmts", "true"); 25 | config.addDataSourceProperty("prepStmtCacheSize", "250"); 26 | config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); 27 | ds = new HikariDataSource(config); 28 | } 29 | } 30 | } 31 | 32 | return ds; 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/PostgresCreateJDBC.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import java.util.*; 4 | 5 | import com.microsoft.azure.functions.annotation.*; 6 | import com.zaxxer.hikari.HikariConfig; 7 | import com.zaxxer.hikari.HikariDataSource; 8 | import com.damoo.samples.helpers.DSInstance; 9 | import com.microsoft.azure.functions.*; 10 | 11 | import java.sql.Connection; 12 | import java.sql.Statement; 13 | 14 | /** 15 | * Azure Functions with HTTP Trigger. 16 | */ 17 | public class PostgresCreateJDBC{ 18 | 19 | @FunctionName("PostgresCreateJDBC") 20 | public HttpResponseMessage run( 21 | @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, 22 | final ExecutionContext context) { 23 | context.getLogger().info("Java HTTP trigger processed a request."); 24 | 25 | try { 26 | Connection c = DSInstance.GetDS().getConnection(); 27 | 28 | Statement stmt = c.createStatement(); 29 | String sql = "INSERT INTO public.funcoutput (\"CorrelationId\", \"Body\") " 30 | + "VALUES ('12345667778', 'Coming from JDBC');"; 31 | 32 | stmt.executeUpdate(sql); 33 | stmt.close(); 34 | c.close(); 35 | } catch (Exception e) { 36 | System.err.println( e.getClass().getName()+": "+ e.getMessage() ); 37 | System.exit(0); 38 | } 39 | 40 | return request.createResponseBuilder(HttpStatus.OK).build(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/CosmosFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | import com.damoo.samples.models.CosmosObj; 3 | import com.microsoft.azure.functions.annotation.*; 4 | 5 | import com.microsoft.azure.functions.*; 6 | 7 | /** 8 | * Azure Function with Cosmos DB trigger and Cosmos output 9 | */ 10 | public class CosmosFunc { 11 | /** 12 | * This function will be invoked when there are inserts or updates in the specified database and collection. 13 | */ 14 | @FunctionName("CosmosFunc") 15 | public void run( 16 | @CosmosDBTrigger( 17 | name = "items", 18 | databaseName = "%DatabaseName%", 19 | collectionName = "%InputCollectionName%", 20 | leaseCollectionName="%LeaseCollectionName%", 21 | connectionStringSetting = "CosmosConStr", 22 | createLeaseCollectionIfNotExists = true 23 | ) 24 | CosmosObj[] items, 25 | @CosmosDBOutput( 26 | name = "cosmosOutput", 27 | connectionStringSetting = "CosmosConStr", 28 | createIfNotExists = true, 29 | databaseName = "%DatabaseName%", 30 | collectionName = "%OutputCollectionName%" 31 | ) OutputBinding outputObjs, 32 | final ExecutionContext context 33 | ) { 34 | 35 | // loop items and add arbritrary value, just because we can... 36 | for(CosmosObj obj : items){ 37 | obj.name = obj.name + "--UPDATED"; 38 | } 39 | 40 | outputObjs.setValue(items); 41 | 42 | context.getLogger().info("Java Cosmos DB trigger function executed."); 43 | context.getLogger().info("Documents count: " + items.length); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/StorageTableQueueFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import java.util.*; 4 | import com.microsoft.azure.functions.annotation.*; 5 | import com.damoo.samples.models.HttpInputObj; 6 | import com.damoo.samples.models.QueueObj; 7 | import com.damoo.samples.models.StorageTableObj; 8 | import com.microsoft.azure.functions.*; 9 | 10 | /** 11 | * Azure Functions with HTTP Trigger, pushing to Storage Queue and Table 12 | */ 13 | public class StorageTableQueueFunc { 14 | /** 15 | * Accepts a custom object from Http Post 16 | */ 17 | @FunctionName("StorageTableQueueFunc") 18 | public HttpResponseMessage run( 19 | @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> req, 20 | @TableOutput(name = "table", connection = "StorageAccount", dataType = "", tableName = "%StorageTableName%") OutputBinding tableOutput, 21 | @QueueOutput(name = "queue", connection = "StorageAccount", dataType = "", queueName = "%StorageQueueName%") OutputBinding queueOutput, 22 | final ExecutionContext context) { 23 | context.getLogger().info("Java HTTP trigger processed a request."); 24 | 25 | // get object 26 | HttpInputObj input = req.getBody().get(); 27 | 28 | // table 29 | StorageTableObj tObj = new StorageTableObj(UUID.randomUUID().toString(), "demo", input.name, input.favouriteFruit); 30 | tableOutput.setValue(tObj); 31 | 32 | // storage queue 33 | QueueObj qObj = new QueueObj(input.name, input.favouriteFruit); 34 | queueOutput.setValue(qObj); 35 | 36 | // return a 202 37 | return req.createResponseBuilder(HttpStatus.ACCEPTED).build(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /java-func-samples/src/test/java/com/damoo/samples/CosmosFuncTests.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import org.junit.Test; 4 | 5 | import com.damoo.samples.models.CosmosObj; 6 | import com.microsoft.azure.functions.*; 7 | import java.util.logging.Logger; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | import static org.mockito.Mockito.doReturn; 11 | import static org.mockito.Mockito.mock; 12 | 13 | 14 | /** 15 | * Unit test for Cosmos Functions. 16 | */ 17 | public class CosmosFuncTests { 18 | /** 19 | * Test output is a copy of the input, with correct updates 20 | */ 21 | @Test 22 | public void outputIsCopyOfInput() throws Exception { 23 | // arrange 24 | CosmosObj[] input = new CosmosObj[3]; 25 | input[0] = new CosmosObj("Test1", "Apples"); 26 | input[1] = new CosmosObj("Test2", "Pears"); 27 | input[2] = new CosmosObj("Test3", "Bananas"); 28 | 29 | CosmosFunc func = new CosmosFunc(); 30 | final ExecutionContext context = mock(ExecutionContext.class); 31 | doReturn(Logger.getGlobal()).when(context).getLogger(); 32 | 33 | OutputBinding output = new OutputBinding(){ 34 | private CosmosObj[] val; 35 | @Override 36 | public void setValue(CosmosObj[] value) { 37 | this.val = value; 38 | } 39 | @Override 40 | public CosmosObj[] getValue() { 41 | return val; 42 | } 43 | }; 44 | 45 | // act 46 | func.run(input, output, context); 47 | 48 | // assert 49 | assertEquals("Test1--UPDATED", output.getValue()[0].name); 50 | assertEquals("Test2--UPDATED", output.getValue()[1].name); 51 | assertEquals("Test3--UPDATED", output.getValue()[2].name); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /java-func-samples/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /java-func-samples/src/test/java/com/damoo/samples/FunctionTests.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import org.junit.Test; 4 | 5 | import com.microsoft.azure.functions.*; 6 | import org.mockito.invocation.InvocationOnMock; 7 | import org.mockito.stubbing.Answer; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | import java.util.Optional; 12 | import java.util.logging.Logger; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | import static org.mockito.ArgumentMatchers.any; 16 | import static org.mockito.Mockito.doAnswer; 17 | import static org.mockito.Mockito.doReturn; 18 | import static org.mockito.Mockito.mock; 19 | 20 | /** 21 | * Unit test for Function class. 22 | */ 23 | public class FunctionTests { 24 | /** 25 | * Boilerplate: Unit test for HttpTriggerJava method. 26 | */ 27 | @Test 28 | public void testHttpTriggerJava() throws Exception { 29 | // Setup 30 | @SuppressWarnings("unchecked") 31 | final HttpRequestMessage> req = mock(HttpRequestMessage.class); 32 | 33 | final Map queryParams = new HashMap<>(); 34 | queryParams.put("name", "Azure"); 35 | doReturn(queryParams).when(req).getQueryParameters(); 36 | 37 | final Optional queryBody = Optional.empty(); 38 | doReturn(queryBody).when(req).getBody(); 39 | 40 | doAnswer(new Answer() { 41 | @Override 42 | public HttpResponseMessage.Builder answer(InvocationOnMock invocation) { 43 | HttpStatus status = (HttpStatus) invocation.getArguments()[0]; 44 | return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status); 45 | } 46 | }).when(req).createResponseBuilder(any(HttpStatus.class)); 47 | 48 | final ExecutionContext context = mock(ExecutionContext.class); 49 | doReturn(Logger.getGlobal()).when(context).getLogger(); 50 | 51 | // Invoke 52 | final HttpResponseMessage ret = new HttpFunc().run(req, context); 53 | 54 | // Verify 55 | assertEquals(ret.getStatus(), HttpStatus.OK); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /java-func-samples/src/test/java/com/damoo/samples/HttpResponseMessageMock.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.*; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * The mock for HttpResponseMessage, can be used in unit tests to verify if the 9 | * returned response by HTTP trigger function is correct or not. 10 | */ 11 | public class HttpResponseMessageMock implements HttpResponseMessage { 12 | private int httpStatusCode; 13 | private HttpStatusType httpStatus; 14 | private Object body; 15 | private Map headers; 16 | 17 | public HttpResponseMessageMock(HttpStatusType status, Map headers, Object body) { 18 | this.httpStatus = status; 19 | this.httpStatusCode = status.value(); 20 | this.headers = headers; 21 | this.body = body; 22 | } 23 | 24 | @Override 25 | public HttpStatusType getStatus() { 26 | return this.httpStatus; 27 | } 28 | 29 | @Override 30 | public int getStatusCode() { 31 | return httpStatusCode; 32 | } 33 | 34 | @Override 35 | public String getHeader(String key) { 36 | return this.headers.get(key); 37 | } 38 | 39 | @Override 40 | public Object getBody() { 41 | return this.body; 42 | } 43 | 44 | public static class HttpResponseMessageBuilderMock implements HttpResponseMessage.Builder { 45 | private Object body; 46 | private int httpStatusCode; 47 | private Map headers; 48 | private HttpStatusType httpStatus; 49 | 50 | public Builder status(HttpStatus status) { 51 | this.httpStatusCode = status.value(); 52 | this.httpStatus = status; 53 | return this; 54 | } 55 | 56 | @Override 57 | public Builder status(HttpStatusType httpStatusType) { 58 | this.httpStatusCode = httpStatusType.value(); 59 | this.httpStatus = httpStatusType; 60 | return this; 61 | } 62 | 63 | @Override 64 | public HttpResponseMessage.Builder header(String key, String value) { 65 | this.headers.put(key, value); 66 | return this; 67 | } 68 | 69 | @Override 70 | public HttpResponseMessage.Builder body(Object body) { 71 | this.body = body; 72 | return this; 73 | } 74 | 75 | @Override 76 | public HttpResponseMessage build() { 77 | return new HttpResponseMessageMock(this.httpStatus, this.headers, this.body); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /java-func-samples/src/test/java/com/damoo/samples/ServiceBusFuncTests.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import org.junit.Test; 4 | 5 | import com.damoo.samples.models.QueueObj; 6 | import com.microsoft.azure.functions.*; 7 | 8 | import java.util.Optional; 9 | import java.util.logging.Logger; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | import static org.mockito.Mockito.doReturn; 13 | import static org.mockito.Mockito.mock; 14 | 15 | 16 | /** 17 | * Unit test for Service Bus Functions. 18 | */ 19 | public class ServiceBusFuncTests { 20 | /** 21 | * Test output is a copy of the input. 22 | */ 23 | @Test 24 | public void outputIsCopyOfInput() throws Exception { 25 | // arrange 26 | QueueObj input = new QueueObj("Test1", "Bananas"); 27 | 28 | ServiceBusProducerFunc func = new ServiceBusProducerFunc(); 29 | final ExecutionContext context = mock(ExecutionContext.class); 30 | doReturn(Logger.getGlobal()).when(context).getLogger(); 31 | 32 | OutputBinding output = new OutputBinding(){ 33 | private QueueObj val; 34 | @Override 35 | public void setValue(QueueObj value) { 36 | this.val = value; 37 | } 38 | @Override 39 | public QueueObj getValue() { 40 | return val; 41 | } 42 | }; 43 | 44 | // mock http req with custom object 45 | final HttpRequestMessage> req = mock(HttpRequestMessage.class); 46 | final Optional queryBody = Optional.of(input); 47 | doReturn(queryBody).when(req).getBody(); 48 | 49 | // act 50 | func.run(req, output, context); 51 | 52 | // assert 53 | assertEquals("Test1", output.getValue().name); 54 | } 55 | 56 | /** 57 | * Test queue 1 copies to queue 2 58 | */ 59 | @Test 60 | public void queue1CopiesToQueue2() throws Exception { 61 | // arrange 62 | QueueObj input = new QueueObj("Test1", "Bananas"); 63 | 64 | ServiceBusConsumerFunc func = new ServiceBusConsumerFunc(); 65 | final ExecutionContext context = mock(ExecutionContext.class); 66 | doReturn(Logger.getGlobal()).when(context).getLogger(); 67 | 68 | OutputBinding output = new OutputBinding(){ 69 | private QueueObj val; 70 | @Override 71 | public void setValue(QueueObj value) { 72 | this.val = value; 73 | } 74 | @Override 75 | public QueueObj getValue() { 76 | return val; 77 | } 78 | }; 79 | 80 | // act 81 | func.run(input, output, context); 82 | 83 | // assert 84 | assertEquals("Test1", output.getValue().name); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/TimerQueueMonitorFunc.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import java.time.*; 4 | import com.microsoft.azure.functions.annotation.*; 5 | import com.microsoft.azure.servicebus.management.ManagementClient; 6 | import com.microsoft.azure.servicebus.management.MessageCountDetails; 7 | import com.microsoft.azure.servicebus.management.QueueRuntimeInfo; 8 | import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; 9 | import com.microsoft.azure.servicebus.primitives.ServiceBusException; 10 | import com.microsoft.applicationinsights.TelemetryClient; 11 | import com.microsoft.applicationinsights.TelemetryConfiguration; 12 | import com.microsoft.azure.functions.*; 13 | 14 | /** 15 | * Azure Functions with Timer trigger, logging message details to App Insights 16 | */ 17 | public class TimerQueueMonitorFunc { 18 | /** 19 | * This function will be invoked periodically according to the specified 20 | * schedule. 21 | * 22 | * @throws InterruptedException 23 | * @throws ServiceBusException 24 | */ 25 | @FunctionName("TimerQueueMonitorFunc") 26 | public void run(@TimerTrigger(name = "timerInfo", schedule = "5 * * * * *") String timerInfo, 27 | final ExecutionContext context) throws ServiceBusException, InterruptedException { 28 | context.getLogger().info("Checking queues at: " + LocalDateTime.now()); 29 | 30 | String telemetryKey = System.getenv("APPINSIGHTS_INSTRUMENTATIONKEY"); 31 | String serviceBusConStr = System.getenv("ServiceBusConStr"); 32 | String queueName1 = System.getenv("SBInputQueue"); 33 | String queueName2 = System.getenv("SBOutputQueue"); 34 | 35 | // for more configuration options you can use the ApplicationInsights.xml file 36 | // - see https://docs.microsoft.com/en-gb/azure/azure-monitor/app/java-get-started#3-add-an-applicationinsightsxml-file 37 | TelemetryConfiguration.getActive().setInstrumentationKey(telemetryKey); 38 | TelemetryClient teleClient = new TelemetryClient(); 39 | 40 | // check queue 1 41 | ManagementClient manageClt = new ManagementClient(new ConnectionStringBuilder(serviceBusConStr, queueName1)); 42 | QueueRuntimeInfo info = manageClt.getQueueRuntimeInfo(queueName1); 43 | MessageCountDetails msgCount = info.getMessageCountDetails(); 44 | teleClient.trackMetric(queueName1 + "-Active-Length", msgCount.getActiveMessageCount()); 45 | teleClient.trackMetric(queueName1 + "-Deadletter-Length", msgCount.getDeadLetterMessageCount()); 46 | teleClient.trackMetric(queueName1 + "-Scheduled-Length", msgCount.getScheduledMessageCount()); 47 | 48 | // check queue 2 49 | manageClt = new ManagementClient(new ConnectionStringBuilder(serviceBusConStr, queueName2)); 50 | info = manageClt.getQueueRuntimeInfo(queueName2); 51 | msgCount = info.getMessageCountDetails(); 52 | teleClient.trackMetric(queueName2 + "-Active-Length", msgCount.getActiveMessageCount()); 53 | teleClient.trackMetric(queueName2 + "-Deadletter-Length", msgCount.getDeadLetterMessageCount()); 54 | teleClient.trackMetric(queueName2 + "-Scheduled-Length", msgCount.getScheduledMessageCount()); 55 | 56 | // teleClient.flush(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /java-func-samples/src/main/java/com/damoo/samples/BlobTriggeredOCR.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import com.microsoft.azure.functions.annotation.*; 4 | import com.microsoft.azure.functions.*; 5 | 6 | import java.net.URI; 7 | 8 | import org.apache.http.HttpEntity; 9 | import org.apache.http.HttpResponse; 10 | import org.apache.http.client.methods.HttpPost; 11 | import org.apache.http.entity.ByteArrayEntity; 12 | import org.apache.http.client.utils.URIBuilder; 13 | import org.apache.http.impl.client.CloseableHttpClient; 14 | import org.apache.http.impl.client.HttpClientBuilder; 15 | import org.apache.http.util.EntityUtils; 16 | import org.json.JSONObject; 17 | 18 | /** 19 | * Azure Function with Azure Blob trigger, blob output and Computer Vision generated OCR output 20 | */ 21 | public class BlobTriggeredOCR { 22 | /** 23 | * 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. 24 | */ 25 | @FunctionName("BlobTriggeredOCR") 26 | @StorageAccount("StorageAccount") 27 | public void run( 28 | @BlobTrigger(name = "content", path = "samples-workitems/{name}", dataType = "binary") byte[] content, 29 | @BindingName("name") String name, 30 | final ExecutionContext context 31 | ) { 32 | context.getLogger().info("Java Blob trigger function processed a blob. Name: " + name + "\n Size: " + content.length + " Bytes"); 33 | 34 | runSample(context, content); 35 | } 36 | 37 | private static final String subscriptionKey = "%ComputerVisionSubscriptionKey%"; 38 | 39 | private static final String uriBase = "https://westeurope.api.cognitive.microsoft.com/vision/v2.0/ocr"; 40 | 41 | public static void runSample(ExecutionContext context, byte[] content) { 42 | CloseableHttpClient httpClient = HttpClientBuilder.create().build(); 43 | 44 | try { 45 | URIBuilder uriBuilder = new URIBuilder(uriBase); 46 | 47 | uriBuilder.setParameter("language", "unk"); 48 | uriBuilder.setParameter("detectOrientation", "true"); 49 | 50 | // Request parameters. 51 | URI uri = uriBuilder.build(); 52 | HttpPost request = new HttpPost(uri); 53 | 54 | // Request headers. 55 | request.setHeader("Content-Type", "application/octet-stream"); 56 | request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKey); 57 | 58 | // Request body. 59 | ByteArrayEntity requestEntity = new ByteArrayEntity(content); 60 | request.setEntity(requestEntity); 61 | 62 | // Call the REST API method and get the response entity. 63 | HttpResponse response = httpClient.execute(request); 64 | HttpEntity entity = response.getEntity(); 65 | 66 | if (entity != null) { 67 | // Format and display the JSON response. 68 | String jsonString = EntityUtils.toString(entity); 69 | JSONObject json = new JSONObject(jsonString); 70 | context.getLogger().info("REST Response:\n"); 71 | context.getLogger().info(json.toString(2)); 72 | } 73 | } catch (Exception e) { 74 | // Display error message. 75 | context.getLogger().info(e.getMessage()); 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure Functions: Java Samples 2 | This repo contains a number of basic samples of Functions written in Java to get you started. 3 | 4 | > **NOTE** The samples provided here are just that, *samples*. They are not ready to be used straight in production, but are intented to get you started with some of the terminology and structure. 5 | 6 | It also contains a few basic [unit tests and an integration test](/java-func-samples/src/test/java/com/damoo/samples) to exercise some basic Functions and give you some jumping-off points. 7 | 8 | It includes... 9 | 10 | | Function | Trigger | Input | Output Binding(s) | 11 | |--|--|--|--| 12 | | [**HttpFunc**](/java-func-samples/src/main/java/com/damoo/samples/HttpFunc.java) | HttpTrigger | HttpRequestMessage | - | 13 | | [**BlobTriggerOutput**](/java-func-samples/src/main/java/com/damoo/samples/BlobTriggerOutput.java) | BlobTrigger | byte[] from trigger | Blob | 14 | | [**CosmosFunc**](/java-func-samples/src/main/java/com/damoo/samples/CosmosFunc.java) | CosmosTrigger | POJO from trigger | CosmosOutput| 15 | | [**ServiceBusProducerFunc**](/java-func-samples/src/main/java/com/damoo/samples/ServiceBusProducerFunc.java) | HttpTrigger | POJO from Http Post | ServiceBusOutput | 16 | | [**ServiceBusConsumerFunc**](/java-func-samples/src/main/java/com/damoo/samples/ServiceBusConsumerFunc.java) | ServiceBusTrigger | POJO from trigger | ServiceBusOutput | 17 | | [**ServiceBusTopicProducerFunc**](/java-func-samples/src/main/java/com/damoo/samples/ServiceBusTopicProducerFunc.java) | HttpTrigger | POJO from Http Post | ServiceBusTopicOutput | 18 | | [**ServiceBusTopicConsumerFunc**](/java-func-samples/src/main/java/com/damoo/samples/ServiceBusTopicConsumerFunc.java) | ServiceBusTopicTrigger | POJO from trigger | ServiceBusTopicOutput | 19 | | [**StorageTableQueue**](/java-func-samples/src/main/java/com/damoo/samples/StorageTableQueueFunc.java) | HttpTrigger | POJO from Http | StorageOutput / TableOutput 20 | | [**EventGridFunc**](/java-func-samples/src/main/java/com/damoo/samples/EventGridFunc.java) | EventGridTrigger | POJO from event grid trigger | CosmosOutput | 21 | | [**HttpKeyVaultFunc**](/java-func-samples/src/main/java/com/damoo/samples/HttpKeyVaultFunc.java) | HttpTrigger | - | (gets arbritrary value from Key Vault) 22 | | [**BlobTriggeredOCR**](/java-func-samples/src/main/java/com/damoo/samples/BlobTriggeredOCR.java) | BlobTrigger | byte[] from trigger | JSON OCR data for incoming Blob | 23 | | [**TimerQueueMonitorFunc.java**](/java-func-samples/src/main/java/com/damoo/samples/TimerQueueMonitorFunc.java) | TimerTrigger | - | Logs metrics to AppInsights | 24 | | [**PostgresCreateJDBC.java**](/java-func-samples/src/main/java/com/damoo/samples/PostgresCreateJDBC.java) | HttpTrigger | - | Sends a row of data to Postgres via JDBC | 25 | ## Local Settings 26 | The following local / app settings are used: *(local storage and Cosmos emulators used in dev)* 27 | ```JSON 28 | { 29 | "IsEncrypted": false, 30 | "Values": { 31 | "AzureWebJobsStorage": "UseDevelopmentStorage=true", 32 | "FUNCTIONS_WORKER_RUNTIME": "java", 33 | "MyKVSecret": "@Microsoft.KeyVault(SecretUri=uri-to-a-secret-value)", 34 | "CosmosConStr": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", 35 | "DatabaseName": "my-db", 36 | "InputCollectionName": "my-col", 37 | "OutputCollectionName": "my-col-output", 38 | "LeaseCollectionName": "my-lease", 39 | "EventsCollectionName": "my-events", 40 | "ServiceBusConStr": "service-bus-con-string-here", 41 | "SBInputQueue": "in-queue", 42 | "SBOutputQueue": "out-queue", 43 | "StorageAccount": "UseDevelopmentStorage=true", 44 | "StorageTableName": "outtable", 45 | "StorageQueueName": "outqueue", 46 | "ComputerVisionSubscriptionKey": "computer-vision-key", 47 | "APPINSIGHTS_INSTRUMENTATIONKEY": "app-insights-key", 48 | "JDBCUrl": "jdbc:postgresql://hostname-of-db-server/db-name", 49 | "DBUsername" : "db-username", 50 | "DBPassword": "db-password" 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /java-func-samples/src/test/java/com/damoo/samples/ServiceBusFuncIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package com.damoo.samples; 2 | 3 | import org.apache.http.HttpEntity; 4 | import org.apache.http.HttpResponse; 5 | import org.apache.http.client.methods.HttpPost; 6 | import org.apache.http.client.utils.URIBuilder; 7 | import org.apache.http.entity.StringEntity; 8 | import org.apache.http.impl.client.CloseableHttpClient; 9 | import org.apache.http.impl.client.HttpClientBuilder; 10 | import org.junit.Test; 11 | 12 | import static org.junit.Assert.assertEquals; 13 | 14 | import java.net.URI; 15 | import java.util.concurrent.CompletableFuture; 16 | 17 | import com.microsoft.azure.servicebus.*; 18 | import com.microsoft.azure.servicebus.management.*; 19 | import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; 20 | 21 | /** 22 | * Integration test for Http + Service Bus Functions. 23 | * Run manually when needed to ensure http / queue 1 / queue 2 are hooked up correctly 24 | * All other times, comment out @test attribute to prevent it being run on mvn verify 25 | */ 26 | public class ServiceBusFuncIntegrationTests { 27 | 28 | //@Test 29 | public void functionChainingTest() throws Exception { 30 | 31 | String connectionString = "service-bus-connection-string-here"; 32 | String inQueueName = "in-queue"; 33 | String outQueueName = "out-queue"; 34 | String producerFuncUrl = "https://your-function-here.azurewebsites.net/api/ServiceBusProducerFunc"; 35 | String funcKey = "func-key-here"; 36 | int numItems = 100; // if higher than 1000 need to update clean queue method below 37 | 38 | // clear out queues 39 | ClearQueue(connectionString, inQueueName); 40 | ClearQueue(connectionString, outQueueName); 41 | 42 | CloseableHttpClient httpTextClient = HttpClientBuilder.create().build(); 43 | URIBuilder builder; 44 | 45 | // POST a bunch of http 46 | try { 47 | builder = new URIBuilder(producerFuncUrl); 48 | 49 | // Prepare the URI for the REST API method. 50 | URI uri = builder.build(); 51 | 52 | for(int i = 0; i onMessageAsync(IMessage message) { 89 | return null; 90 | } 91 | 92 | @Override 93 | public void notifyException(Throwable exception, ExceptionPhase phase) {} 94 | }); 95 | Thread.sleep(5000); 96 | getQ.close(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /java-func-samples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.damoo.samples 7 | java-func-samples 8 | 1.0-SNAPSHOT 9 | jar 10 | 11 | Azure Java Functions 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 1.3.1 18 | 1.3.0 19 | damoo-java-func 20 | uksouth 21 | ${project.build.directory}/azure-functions/${functionAppName} 22 | java-func 23 | 24 | 25 | 26 | 27 | maven.snapshots 28 | Maven Central Snapshot Repository 29 | https://oss.sonatype.org/content/repositories/snapshots/ 30 | 31 | false 32 | 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | maven.snapshots 42 | Maven Central Snapshot Repository 43 | https://oss.sonatype.org/content/repositories/snapshots/ 44 | 45 | false 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | junit 57 | junit 58 | 4.12 59 | 60 | 61 | org.mockito 62 | mockito-core 63 | 2.4.0 64 | 65 | 66 | com.microsoft.azure.functions 67 | azure-functions-java-library 68 | ${azure.functions.java.library.version} 69 | 70 | 71 | org.json 72 | json 73 | 20180130 74 | 75 | 76 | org.apache.httpcomponents 77 | httpclient 78 | 4.5.5 79 | 80 | 81 | org.apache.httpcomponents 82 | httpcore 83 | 4.4.9 84 | 85 | 86 | 87 | 88 | 89 | 90 | com.microsoft.azure.functions 91 | azure-functions-java-library 92 | 93 | 94 | com.microsoft.azure 95 | azure-servicebus 96 | 2.0.0 97 | 98 | 99 | com.microsoft.azure 100 | applicationinsights-core 101 | 2.0.0 102 | 103 | 104 | org.apache.httpcomponents 105 | httpcore 106 | 4.4.9 107 | 108 | 109 | org.apache.httpcomponents 110 | httpclient 111 | 4.5.5 112 | 113 | 114 | org.json 115 | json 116 | 20180130 117 | 118 | 119 | org.postgresql 120 | postgresql 121 | 42.2.5 122 | runtime 123 | 124 | 134 | 135 | com.zaxxer 136 | HikariCP 137 | 2.7.8 138 | compile 139 | 140 | 141 | 142 | junit 143 | junit 144 | test 145 | 146 | 147 | org.mockito 148 | mockito-core 149 | test 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | com.microsoft.azure 158 | azure-functions-maven-plugin 159 | ${azure.functions.maven.plugin.version} 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-resources-plugin 164 | 3.1.0 165 | 166 | 167 | org.apache.maven.plugins 168 | maven-dependency-plugin 169 | 3.1.1 170 | 171 | 172 | org.apache.maven.plugins 173 | maven-jar-plugin 174 | 175 | 176 | 177 | com.damoo.samples.DataJPACreate 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | org.apache.maven.plugins 189 | maven-surefire-plugin 190 | 191 | 192 | true 193 | 194 | false 195 | 196 | 197 | 198 | unit-tests 199 | test 200 | 201 | test 202 | 203 | 204 | 205 | false 206 | 207 | 208 | **/*Tests.java 209 | 210 | 211 | 212 | **/*IntegrationTests.java 213 | 214 | 215 | 216 | 217 | integration-tests 218 | integration-test 219 | 220 | test 221 | 222 | 223 | 224 | false 225 | 226 | 227 | **/*IntegrationTests.java 228 | 229 | 230 | 231 | 232 | 233 | 234 | com.microsoft.azure 235 | azure-functions-maven-plugin 236 | 237 | ${functionResourceGroup} 238 | ${functionAppName} 239 | ${functionAppRegion} 240 | 241 | 242 | 243 | WEBSITE_RUN_FROM_PACKAGE 244 | 1 245 | 246 | 247 | FUNCTIONS_EXTENSION_VERSION 248 | ~2 249 | 250 | 251 | FUNCTIONS_WORKER_RUNTIME 252 | java 253 | 254 | 255 | 256 | 257 | 258 | package-functions 259 | 260 | package 261 | 262 | 263 | 264 | 265 | 266 | org.apache.maven.plugins 267 | maven-resources-plugin 268 | 269 | 270 | copy-resources 271 | package 272 | 273 | copy-resources 274 | 275 | 276 | true 277 | ${stagingDirectory} 278 | 279 | 280 | ${project.basedir} 281 | 282 | host.json 283 | local.settings.json 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | org.apache.maven.plugins 293 | maven-dependency-plugin 294 | 295 | 296 | copy-dependencies 297 | prepare-package 298 | 299 | copy-dependencies 300 | 301 | 302 | ${stagingDirectory}/lib 303 | false 304 | false 305 | true 306 | runtime 307 | azure-functions-java-library 308 | 309 | 310 | 311 | 312 | 313 | 314 | maven-clean-plugin 315 | 3.1.0 316 | 317 | 318 | 319 | obj 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | --------------------------------------------------------------------------------