Deploy Java Functions to Azure Function App

 

Objective

You have a working Azure Java Function and the source code is managed in a Git repository. The goal of the tutorial is to automate the deployment of one or more Java Functions to an Azure Function App.  This automation will include:

  • cloning the Java application from a Git repository

  • compiling the Java Function

  • packaging the Java executable and Application Setting/Connection String properties file

  • update relevant Application Setting and Connection String properties in Azure Function App

  • deploying the Java Function(s) to Azure Function App

  • retrieve the deployment log (optional) against the deployment executed

We will walk through each of the FlexDeploy features that will be created/configured to accomplish this goal and have the Java Function deployed in a very short amount of time.

Checklist

Checklist

Description

Checklist

Description

Azure Tenant Id

Azure Tenant Id for the company

Azure Subscription Id

Azure Subscription where the Function App exists

Azure Client ID

Client ID to connect to desired Azure Subscription

Azure Client Key

Password for the Client ID

Azure Client ID permission

The Client ID must have relevant access in target Function App to deploy code

Azure Function App

The Function App with relevant runtime should already be created

Azure Resource Group

The Resource Group containing the Function App

Azure CLI installation

Azure CLI needs to be installed where the plugin operation will run (generally on FlexDeploy server)

Azure CLI in class path

Azure CLI should be added to the path on the server where the plugin operation will run. Otherwise, the path can also be set using FlexDeploy target level property

Configure Cloud Account

First, an Azure account needs to be configured under Topology. FlexDeploy will connect to the right Azure Subscription with provided details to run the deployment.

  • Navigate to Integrations

  • Open the Cloud tab

  • Create a new Cloud account by pressing the Create button. The provider type should be Azure

It should have a Client ID, Client Key, Tenant Id, and Subscription Id configured in it. The Client ID must have relevant access in the target Function App to deploy code and make other associated changes. (Application Setting update, etc.)

Git Repository Structure

The Git repository should contain the function codebase. Alongside it can also contain any application setting and connection string related attributes in respective files (any naming convention allowed). These files are not mandatory, however, in case someone has any Application Setting and Connection String property to update this is recommended. Please review the Application Setting and Connection String Property Update section for a more detailed explanation.

A sample Git repository structure is given below:

Build and Deploy Workflows

Build Workflow

Navigate to Workflows and create a workflow using the button as highlighted below.

The steps of the workflow execution can be configured from the Definition tab. Below is a sample build workflow.

Step 1: Clone Git Repository

This step will clone the Git repository codebase into the Project’s execution working directory. The Git URL will be retrieved from Source Control configured under Project configuration.

Below given is the Git code structure and corresponding exported codebase during execution as a result of the above step.

Git Codebase

Exported Codebase

Step 2: Execute Maven Build

The below step will execute the Maven build with the project’s pom.xml and create a Java executable (.jar) file inside the target directory.

If the pom.xml is properly configured, the java executable will be generated along other essential files as shown below under target/azure-functions folder.

Also, for each Function, a separate folder will be automatically generated with a corresponding function.json file in it.

All of above files need to be copied to Azure Function App to execute properly.

Step 3: Copy Properties File to Intermediate Directory

Application Setting and Connection String json files (if applicable/present) will be moved to the intermediate directory. An intermediate directory can have any name. In this case, we are using the artifactsObjects folder inside the temp directory. File names are mentioned under File Filter separated by ‘##’ (as advised in the description). Application Setting and Connection String values can also be passed as inputs to the deploy workflow. Application Setting and Connection String files are optional. Please review the Application Setting and Connection String property update section for a detailed explanation.

Step 4: Create an Archive of the Executable in Intermediate Directory

Per the Azure Function App deployment requirement, we have created an archive with the java executable and other associated files (generated through Maven) in it.

Source Path: FD_TEMP_DIR + "/JavaFunction/target/azure-functions/azure-functions-sample"

Target Path: FD_TEMP_DIR + '/artifactObjects/deploy.zip'

If we look inside the deploy.zip, it contains the jar file along with other associated files. Basically, it contains all relevant files that need to be copied to the Azure Function App backend. Azure Function App treats the jar file as an executable package and runs it.

The jar file (or any executable files) inside the .zip file shouldn’t be inside any subfolder. If they are, the zip file deployment to Azure may not work.

Step 5: Save All as Artifact from Intermediate Directory

After executing the above steps, the intermediate directory (artifactObjects) should contain files as shown below.

These objects are required as part of the deployment flow. Hence we create an archive (artifacts.zip) with them inside the Artifacts directory. We also check the Produces Artifacts checkbox to save the zip file as an artifact.

Source Path: FD_TEMP_DIR+"/artifactObjects"

Target Path: FD_ARTIFACTS_DIR+"/artifacts.zip"

As part of the above step, all files inside the artifactObjects folder are archived to create an artifacts.zip file which will be saved as an artifact for future reference from the Deployment workflow.

The directory name/artifact name can be anything. The deployment workflow expects only one .zip file inside the artifact containing the executable (.jar file in this case). It will search for a .zip extension and treat it as a package archive for deployment.

The deployFunctions operation of the Azure plugin will search for the Application Setting and Connection String file name provided as part of Project properties. Irrespective of folder structure, it will find the file. In case more than one file exists with the given name, the workflow execution will fail.

Deploy Workflow

Navigate to Workflows and create a workflow using the button as highlighted below.

Below is a sample deployment workflow to deploy the archive to Azure Function App.

Step 1: Deploy Functions

This step first updates the Application Setting/Connection String values from the files present in the artifact (optional). Instead of using Application Setting and Connection String files, you can also directly provide the values as plugin inputs.

In using inputs is preferred, we can create input variables on the deployment workflow like below and use them in the deployFunctions operation.

Open the Inputs popup within the deploy workflow and create the two inputs.

The input arguments can then be used in the deployFunctions operation as shown below. The plugin will take the input values and process them accordingly.

The deployFunctions operation returns four output variables. To capture them and use them for further processing/evaluation, you can create variables and map them against the output parameters of deployFunctions operation. Open the X2 variables popup and create the four variables, making sure to check the Return As Output option. Map the variables against the outputs of the deployFunctions operation to capture the responses (shown above).

Project Configuration

Navigate to Projects and create a Project with a logical name (JavaAzureFunction in this case)

Configure the build and deploy workflows which were created in previous steps.

Source Control

Configure the SCM repository on the Source Control tab.

  1. Select the Sources section for configuring your source repository

  2. Select the appropriate Source Control Type

  3. Configure source repository details. For more detailed steps of source control configuration, please refer to Configure Source Control in FlexDeploy

Project Properties

To configure Project-specific properties, navigate to Configuration → Properties.

  1. To deploy a Function to Azure Function App, the first two mandatory properties are the Function App Name and Resource Group Name.

  2. Remote Build: This flag is applicable in case we want to upload the code to the Azure Function App backend and build it there itself (e.g.: .NET/Node.js). We are creating the Java executable (jar) file explicitly as part of the build workflow, hence this checkbox can be left unchecked for this scenario.

  3. We also need to provide the Application Setting/Connection String file names (if applicable).

  4. Show Deployment Log: Once deployment is completed, this can be checked if you’d like to verify the execution steps.

    If checked, the plugin will internally retrieve the deployment dd and will fetch the deployment log (if available) and return it as an output variable.

    This is applicable only for code archive deployments (not for Docker image deployment.)

Application Setting and Connection String Property Update

These Application Setting/Connection String properties are not mandatory and can also be provided in the workflow as a plugin input, or you may not need it to be passed at all. However, the following is the recommended way, which assumes the files exist in the working execution directory (folder hierarchy is not required, the plugin will search the file based on the file name).

One application setting and one connection string file are allowed per project.

Application setting and connection string are two separate entities, so whichever files exist will be considered during deployment.

Let’s review the sample application setting file first (same structure as the local.settings.json file). In our scenario, there are two dynamic values that need to be propagated to Function App Application Setting.

DYNAMIC_TESTKEY1: project-specific and independent of environment

DYNAMIC_ENV_TESTKEY2: environment-specific

Both are already added to the AppSettings.json file present in our Git Repository.

Both properties need to be configured in the Workflow Properties with relevant property scope.

To provide the value for DYNAMIC_TESTKEY1 (Project-specific), navigate to the Configuration tab of your Project. Select the Properties tab from the left-hand pane and provide the proper value for the property.

To provide the value for DYNAMIC_ENV_TESTKEY2 (Environment-specific), the same needs to be done within the Target properties. Navigate to Topology and open the intended Target. Provide the value for the property as shown below.

These Application Setting/Connection String values can also be passed as a workflow input to the deployFunction operation. The sample is shown as given below.

Please refer to this page for the input structure of Application Setting and Connection String when passed as a file or as an input parameter - Application Setting/Connection String File and Input Content Acceptable Structure

In the case that both the Application Setting file and Application Setting input argument are passed, a consolidated list of properties will be considered while updating the Function App. If the same attribute is used both in the file and input, the input value will take precedence. The same applies to Connection String as well.

Also, it’s not mandatory to have dynamic values. You can always pass static hard-coded values if needed (although not recommended).

Application Setting and Connection String values will be updated against the Function Slot Name configured at the environment-level. Refer to the Deploy to Slot section for further details.

There could be scenarios where someone only need to update the Application Setting or Connection String without actually deploying the code. In that case, you can use upsertFunctionApplicationSetting or upsertFunctionConnectionString operations respectively. The workflow execution will be exactly the same, but the code archive creation/Docker image update step will not be required. The build workflow’s generated artifact should only contain AppSetting.json or ConnString.json.

Target Properties

Navigate to Topology. Choose a Target Group on the left, or create a new one. You will see a list of Environments on the right with colored circles representing each Target. 

Color coding represents:

  • RED - no required properties are set and/or the Endpoint is not configured

  • YELLOW - some of the required properties are set and/or the Endpoint is not configured

  • GREEN - all required properties are set and the Endpoint is configured

Clicking the environment row for Dev allows modifying the Endpoint and properties. Below are the environment-specific values which need to be updated. Also, if we are adding any environment-specific properties for Application Setting/Connection String (as mentioned in the previous step), those values should also be updated here.

Properties

Mandatory Field

Description

Properties

Mandatory Field

Description

Function Slot Name

Required

Target slot for deployment

Target Slot to Swap

Optional

In case slot swap is required

Azure Cloud Account

Required 

Azure account with relevant details

Absolute Path of Azure CLI

Optional

Not required if Azure CLI already added to workflow execution m/c class path

GIT Path

Optional

Path to the Git executable. Required only if git is not on class path.

Deploy to Slot

Azure Function App default slot is production. However, you can configure multiple slots and deploy Functions on those slots within your Function App. Function Slot Name is a mandatory field, where the code needs to deploy.

In case someone wants to do a slot swap, they can provide the Target Slot to swap with as shown below. The executeFunctionAppSlotSwap operation can be used to perform the slot swap.

Build Execution

For detailed steps on how to initiate a build for an Azure Function, review artifacts, and ultimately deploy to Azure Function App, please refer to Build and Deploy Execution through FlexDeploy

Post-Deployment Debugging

After deploying your project in FlexDeploy, it can take a little while for the function application to be up and running.

Once the application is deployed to Azure Function App through the plugin operation, Azure basically uploads the files to the backend. However, if the application is up and running or failed can’t be verified immediately. It takes a little while for the service to start and accept requests.

Issues can happen if host.json has some issue. A sample error message is shown below.

The function archive generated is not in desired format hence can’t be loaded. A sample error message is shown below.

In such scenario, functions deployed will reflect as none and Azure Function may be in an unreachable state as shown below.

The best way to check logs is using URL https://$func_name.scm.azurewebsites.net/api/logstream or logstream from console. As stated already in above scenarios, in case of failure we can easily debug the issue from logs and get the issue fixed.

Congratulations! You have successfully completed the Java Application deployment to the Azure Function App tutorial.

Now that you have configured FlexDeploy for one Azure Function, it is extremely easy to replicate the same for other Azure Functions. Simply use the Copy Project feature and a new project will be created with all of the configuration completed already. You just need to make the necessary SCM and property configuration changes for your target Azure Function.

 

The following macros are not currently supported in the footer:
  • style