Azure Functions Java developer guide

Programming model

Your Azure function should be a stateless class method that processes input and produces output. Although you are allowed to write instance methods, your function must not depend on any instance fields of the class. All function methods must have a public access modifier.

Triggers and annotations

Typically an Azure function is invoked because of an external trigger. Your function needs to process that trigger and its associated inputs and produce one or more outputs.

Java annotations are included in the azure-functions-java-core package to bind input and outputs to your methods. The supported input triggers and output binding annotations are included in the following table:

Binding Annotation
CosmosDB N/A
HTTP
  • HttpTrigger
  • HttpOutput
Mobile Apps N/A
Notification Hubs N/A
Storage Blob
  • BlobTrigger
  • BlobOutput
  • BlobOutput
Storage Queue
  • QueueTrigger
  • QueueOutput
Storage Table
  • TableInput
  • TableOutput
Timer
  • TimerTrigger
Twilio N/A

Trigger inputs and outputs can also be defined in the function.json for your application.

Important

You must configure an Azure Storage account in your local.settings.json to run Azure Storage Blob, Queue, or Table triggers locally.

Example using annotations:

import com.microsoft.azure.serverless.functions.annotation.HttpTrigger;
import com.microsoft.azure.serverless.functions.ExecutionContext;

public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {"post"},  authLevel = AuthorizationLevel.ANONYMOUS) 
        String req, ExecutionContext context) {
        return String.format(req);
    }
}

The same function written without annotations:

package com.example;

public class MyClass {
    public static String echo(String in) {
        return in;
    }
}

with the corresponding function.json:

{
  "scriptFile": "azure-functions-example.jar",
  "entryPoint": "com.example.MyClass.echo",
  "bindings": [
    {
      "type": "httpTrigger",
      "name": "req",
      "direction": "in",
      "authLevel": "anonymous",
      "methods": [ "post" ]
    },
    {
      "type": "http",
      "name": "$return",
      "direction": "out"
    }
  ]
}

Data Types

You are free to use all the data types in Java for the input and output data, including native types; customized Java types and specialized Azure types defined in azure-functions-java-core package. The Azure Functions runtime attempts convert the input received into the type requested by your code.

Strings

Values passed into function methods will be cast to Strings if the corresponding input parameter type for the function is of type String.

Plain old Java objects (POJOs)

Strings formatted with JSON will be cast to Java types if the input of the function method expects that Java type. This conversion allows you to pass JSON inputs into your functions and work with Java types in your code without having to implement the conversion in your own code.

POJO types used as inputs to functions must the same public access modifier as the function methods they are being used in. You don't have to declare POJO class fields public. For example, a JSON string { "x": 3 } is able to be converted to the following POJO type:

public class MyData {
    private int x;
}

Binary data

Binary data is represented as a byte[] in your Azure functions code. Bind binary inputs or outputs to your functions by setting the dataType field in your function.json to binary:

 {
  "scriptFile": "azure-functions-example.jar",
  "entryPoint": "com.example.MyClass.echo",
  "bindings": [
    {
      "type": "blob",
      "name": "content",
      "direction": "in",
      "dataType": "binary",
      "path": "container/myfile.bin",
      "connection": "ExampleStorageAccount"
    },
  ]
}

Then use it in your function code:

// Class definition and imports are omitted here
public static String echoLength(byte[] content) {
}

Use OutputBinding<byte[]> type to make a binary output binding.

Function method overloading

You are allowed to overload function methods with the same name but with different types. For example, you can have both String echo(String s) and String echo(MyType s) in one class, and Azure Functions runtime decides which one to invoke by examine the actual input type (for HTTP input, MIME type text/plain leads to String while application/json represents MyType).

Inputs

Input are divided into two categories in Azure Functions: one is the trigger input and the other is the additional input. Although they are different in function.json, the usage is identical in Java code. Let's take the following code snippet as an example:

package com.example;

import com.microsoft.azure.serverless.functions.annotation.BindingName;

public class MyClass {
    public static String echo(String in, @BindingName("item") MyObject obj) {
        return "Hello, " + in + " and " + obj.getKey() + ".";
    }

    private static class MyObject {
        public String getKey() { return this.RowKey; }
        private String RowKey;
    }
}

The @BindingName annotation accepts a String property that represents the name of the binding/trigger defined in function.json:

{
  "scriptFile": "azure-functions-example.jar",
  "entryPoint": "com.example.MyClass.echo",
  "bindings": [
    {
      "type": "httpTrigger",
      "name": "req",
      "direction": "in",
      "authLevel": "anonymous",
      "methods": [ "put" ],
      "route": "items/{id}"
    },
    {
      "type": "table",
      "name": "item",
      "direction": "in",
      "tableName": "items",
      "partitionKey": "Example",
      "rowKey": "{id}",
      "connection": "ExampleStorageAccount"
    },
    {
      "type": "http",
      "name": "$return",
      "direction": "out"
    }
  ]
}

So when this function is invoked, the HTTP request payload passes a String for argument in and an Azure Table Storage MyObject type passed to argument obj.

Outputs

Outputs can be expressed both in return value or output parameters. If there is only one output, you are recommended to use the return value. For multiple outputs, you have to use output parameters.

Return value is the simplest form of output, you just return the value of any type, and Azure Functions runtime will try to marshal it back to the actual type (such as an HTTP response). In functions.json, you use $return as the name of the output binding.

To produce multiple output values, use OutputParameter<T> type defined in the azure-functions-java-core package. If you need to make an HTTP response and push a message to a queue as well, you can write something like:

package com.example;

import com.microsoft.azure.serverless.functions.OutputParameter;
import com.microsoft.azure.serverless.functions.annotation.BindingName;

public class MyClass {
    public static String echo(String body, @BindingName("message") OutputParameter<String> queue) {
        String result = "Hello, " + body + ".";
        queue.setValue(result);
        return result;
    }
}

and define the output binding in function.json:

{
  "scriptFile": "azure-functions-example.jar",
  "entryPoint": "com.example.MyClass.echo",
  "bindings": [
    {
      "type": "httpTrigger",
      "name": "req",
      "direction": "in",
      "authLevel": "anonymous",
      "methods": [ "post" ]
    },
    {
      "type": "queue",
      "name": "message",
      "direction": "out",
      "queueName": "myqueue",
      "connection": "ExampleStorageAccount"
    },
    {
      "type": "http",
      "name": "$return",
      "direction": "out"
    }
  ]
}

Specialized Types

Sometimes a function must have detailed control over inputs and outputs. Specialized types in the azure-functions-java-core package are provided for you to manipulate request information and tailor the return status of a HTTP trigger:

Specialized Type Target Typical Usage
HttpRequestMessage HTTP Trigger Get method, headers, or queries
HttpResponseMessage HTTP Output Binding Return status other than 200

Note

You can also use @BindingName annotation to get HTTP headers and queries. For example, @Bind("name") String query iterates the HTTP request headers and queries and pass that value to the method. For example, query will be "test" if the request URL is http://example.org/api/echo?name=test.

Functions execution context

You interact with Azure Functions execution environment via the ExecutionContext object defined in the azure-functions-java-core package. Use the ExecutionContext object to use invocation information and functions runtime information in your code.

Logging

Access to the Functions runtime logger is available through the ExecutionContext object. This logger is tied to the Azure monitor and allows you to flag warnings and errors encountered during function execution.

The following example code logs a warning message when the request body received is empty.

import com.microsoft.azure.serverless.functions.annotation.HttpTrigger;
import com.microsoft.azure.serverless.functions.ExecutionContext;

public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {"post"}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) {
        if (req.isEmpty()) {
            context.getLogger().warning("Empty request body received in " + context.getInvocationId());
        }
        return String.format(req);
    }
}

Next steps

For more information, see the following resources: