Quickstart: Use Java to create and publish a function to Azure Functions

This article instructs you how to build and publish a Java function to Azure functions with the Maven command-line tool. When you're done, your function code runs on the Consumption Plan in Azure and can be triggered using an HTTP request.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites

To develop functions using Java, you must have the following installed:

Important

The JAVA_HOME environment variable must be set to the install location of the JDK to complete this quickstart.

Generate a new Functions project

In an empty folder, run the following command to generate the Functions project from a Maven archetype.

Linux/macOS

mvn archetype:generate \
    -DarchetypeGroupId=com.microsoft.azure \
	-DarchetypeArtifactId=azure-functions-archetype 

Note

If you're experiencing issues with running the command, take a look at what maven-archetype-plugin version is used. Because you are running the command in an empty directory with no .pom file, it might be attempting to use a plugin of the older version from ~/.m2/repository/org/apache/maven/plugins/maven-archetype-plugin if you upgraded your Maven from an older version. If so, try deleting the maven-archetype-plugin directory and re-running the command.

Windows

mvn archetype:generate `
    "-DarchetypeGroupId=com.microsoft.azure" `
    "-DarchetypeArtifactId=azure-functions-archetype"
mvn archetype:generate ^
	"-DarchetypeGroupId=com.microsoft.azure" ^
	"-DarchetypeArtifactId=azure-functions-archetype"

Maven will ask you for values needed to finish generating the project. For groupId, artifactId, and version values, see the Maven naming conventions reference. The appName value must be unique across Azure, so Maven generates an app name based on the previously entered artifactId as a default. The packageName value determines the Java package for the generated function code.

The com.fabrikam.functions and fabrikam-functions identifiers below are used as an example and to make later steps in this quickstart easier to read. You are encouraged to supply your own values to Maven in this step.

Define value for property 'groupId' (should match expression '[A-Za-z0-9_\-\.]+'): com.fabrikam.functions
Define value for property 'artifactId' (should match expression '[A-Za-z0-9_\-\.]+'): fabrikam-functions
Define value for property 'version' 1.0-SNAPSHOT : 
Define value for property 'package': com.fabrikam.functions
Define value for property 'appName' fabrikam-functions-20170927220323382:
Define value for property 'appRegion' westus: :
Define value for property 'resourceGroup' java-functions-group: :
Confirm properties configuration: Y

Maven creates the project files in a new folder with a name of artifactId, in this example fabrikam-functions. The ready to run generated code in the project is an HTTP triggered function that echoes the body of the request. Replace src/main/java/com/fabrikam/functions/Function.java with the following code:

package com.fabrikam.functions;

import java.util.*;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

public class Function {
    /**
     * This function listens at endpoint "/api/HttpTrigger-Java". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpTrigger-Java
     * 2. curl {your host}/api/HttpTrigger-Java?name=HTTP%20Query
     */
    @FunctionName("HttpTrigger-Java")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = { HttpMethod.GET, HttpMethod.POST }, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        // Parse query parameter
        String query = request.getQueryParameters().get("name");
        String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
        }
    }
}

Enable extension bundles

The easiest way to install binding extensions is to enable extension bundles. When you enable bundles, a predefined set of extension packages is automatically installed.

To enable extension bundles, open the host.json file and update its contents to match the following code:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[1.*, 2.0.0)"
    }
}

Run the function locally

Change directory to the newly created project folder (the one containing your host.json and pom.xml files) and build and run the function with Maven:

cd fabrikam-function
mvn clean package 
mvn azure-functions:run

Note

If you're experiencing this exception: javax.xml.bind.JAXBException with Java 9, see the workaround on GitHub.

You see this output when the function is running locally on your system and ready to respond to HTTP requests:

Listening on http://localhost:7071
Hit CTRL-C to exit...

Http Functions:

   hello: http://localhost:7071/api/HttpTrigger-Java

Trigger the function from the command line using curl in a new terminal window:

curl -w "\n" http://localhost:7071/api/HttpTrigger-Java -d LocalFunction
Hello LocalFunction!

Use Ctrl-C in the terminal to stop the function code.

Deploy the function to Azure

The deploy process to Azure Functions uses account credentials from the Azure CLI. Sign in with the Azure CLI before continuing.

az login

Deploy your code into a new Function app using the azure-functions:deploy Maven target. This performs a Zip Deploy with Run From Package mode enabled.

Note

When you use Visual Studio Code to deploy your Function app, remember to choose a non-free subscription, or you will get an error. You can watch your subscription on the left side of the IDE.

mvn azure-functions:deploy

When the deploy is complete, you see the URL you can use to access your Azure function app:

[INFO] Successfully deployed Function App with package.
[INFO] Deleting deployment package from Azure Storage...
[INFO] Successfully deleted deployment package fabrikam-function-20170920120101928.20170920143621915.zip
[INFO] Successfully deployed Function App at https://fabrikam-function-20170920120101928.azurewebsites.net
[INFO] ------------------------------------------------------------------------

Test the function app running on Azure using cURL. You'll need to change the URL from the sample below to match the deployed URL for your own function app from the previous step.

Note

Make sure you set the Access rights to Anonymous. When you choose the default level of Function, you are required to present the function key in requests to access your function endpoint.

curl -w "\n" https://fabrikam-function-20170920120101928.azurewebsites.net/api/HttpTrigger-Java -d AzureFunctions
Hello AzureFunctions!

Make changes and redeploy

Edit the src/main.../Function.java source file in the generated project to alter the text returned by your Function app. Change this line:

return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();

To the following:

return request.createResponseBuilder(HttpStatus.OK).body("Hi, " + name).build();

Save the changes. Run mvn clean package and redeploy by running azure-functions:deploy from the terminal as before. The function app will be updated and this request:

curl -w '\n' -d AzureFunctionsTest https://fabrikam-functions-20170920120101928.azurewebsites.net/api/HttpTrigger-Java

Will have updated output:

Hi, AzureFunctionsTest

Next steps

You have created a Java function app with a simple HTTP trigger and deployed it to Azure Functions.