Guía de Azure Functions para desarrolladores de JavaAzure Functions Java developer guide

El tiempo de ejecución de Azure Functions admite LTS de Java SE 8 (zulu8.31.0.2-jre8.0.181-win_x64).The Azure Functions runtime supports Java SE 8 LTS (zulu8.31.0.2-jre8.0.181-win_x64).

Esta guía contiene información acerca de las complejidades de la escritura de Azure Functions con Java.This guide contains information about the intricacies of writing Azure Functions with Java.

Una función de Java es una public método decorado con anotación @FunctionName.A Java function is a public method decorated with annotation @FunctionName. Este método define la entrada para una función de java y debe ser único en un paquete determinado.This method defines the entry for a java function and must be unique in a given package.

En este artículo se supone que ya ha leído Referencia para desarrolladores de Azure Functions.This article assumes that you have already read the Azure Functions developer reference. También debe completar el inicio rápido de Functions para crear su primera función, mediante Visual Studio Code o con maven.You should also complete the Functions quickstart to create your first function, using Visual Studio Code or using maven.

Modelo de programaciónProgramming model

Los conceptos de desencadenadores y enlaces son fundamentales en Azure Functions.The concepts of triggers and bindings are fundamental to Azure Functions. Los desencadenadores inician la ejecución del código.Triggers start the execution of your code. Los enlaces, por otro lado, proporcionan una manera de pasar y devolver datos de una función, sin tener que escribir un código de acceso a datos personalizados.Bindings give you a way to pass data to and return data from a function, without having to write custom data access code.

Estructura de carpetasFolder structure

Esta es la estructura de carpetas de un proyecto de Java de una función de Azure:Here is the folder structure of an Azure Function Java project:

FunctionsProject
 | - src
 | | - main
 | | | - java
 | | | | - FunctionApp
 | | | | | - MyFirstFunction.java
 | | | | | - MySecondFunction.java
 | - target
 | | - azure-functions
 | | | - FunctionApp
 | | | | - FunctionApp.jar
 | | | | - host.json
 | | | | - MyFirstFunction
 | | | | | - function.json
 | | | | - MySecondFunction
 | | | | | - function.json
 | | | | - bin
 | | | | - lib
 | - pom.xml

Hay un archivo host.json compartido que se puede usar para configurar la aplicación de función.There's a shared host.json file that can be used to configure the function app. Cada función tiene su propio archivo de código (.java) y archivo de configuración de enlace (function.json).Each function has its own code file (.java) and binding configuration file (function.json).

Puede colocar más de una función en un proyecto.You can put more than one function in a project. Evite colocar las funciones en archivos JAR independientes.Avoid putting your functions into separate jars. La aplicación de función del directorio de destino es lo que se implementa en la aplicación de función en Azure.The FunctionApp in the target directory is what gets deployed to your function app in Azure.

Desencadenadores y anotacionesTriggers and annotations

Las funciones de Azure se invocan mediante un desencadenador, como una solicitud HTTP, un temporizador o una actualización de datos.Azure functions are invoked by a trigger, such as an HTTP request, a timer, or an update to data. La función debe procesar ese desencadenador y las demás entradas para generar una o más salidas.Your function needs to process that trigger and any other inputs to produce one or more outputs.

Utilice las anotaciones de Java incluidas en el paquete com.microsoft.azure.functions.annotation.* para enlazar las entradas y salidas a los métodos.Use the Java annotations included in the com.microsoft.azure.functions.annotation.* package to bind input and outputs to your methods. Para obtener más información, consulte documentos de referencia de Java.For more information, see Java reference docs.

Importante

Debe configurar una cuenta de Azure Storage en local.settings.json para ejecutar los desencadenadores de Azure Blob/Queue/Table Storage de manera local.You must configure an Azure Storage account in your local.settings.json to run Azure Storage Blob, Queue, or Table triggers locally.

Ejemplo:Example:

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

Aquí está el elemento function.json correspondiente que generó azure-functions-maven-plugin:here is the generated corresponding function.json by the azure-functions-maven-plugin:

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

Disponibilidad y soporte técnico del entorno de ejecución de JDKJDK runtime availability and support

Descargue y utilice los JDK de Java 8 de Azul Zulu Enterprise for Azure de Azul Systems para el desarrollo local de aplicaciones de función Java.Download and use the Azul Zulu Enterprise for Azure Java 8 JDKs from Azul Systems for local development of Java function apps. Azure Functions usa el entorno en tiempo de ejecución del JDK de Java 8 de Azul al implementar las aplicaciones de función en la nube.Azure Functions uses the Azul Java 8 JDK runtime when you deploy your function apps to the cloud.

El Soporte técnico de Azure para problemas con los JDK y las aplicaciones de función está disponible con un plan de soporte técnico cualificado.Azure support for issues with the JDKs and Function apps is available with a qualified support plan.

Personalización de JVMCustomize JVM

Functions permite personalizar la máquina virtual de Java (JVM) utilizada para ejecutar las funciones de Java.Functions lets you customize the Java virtual machine (JVM) used to execute your Java functions. El siguientes opciones de JVM se usan de forma predeterminada:The following JVM options are used by default:

  • -XX:+TieredCompilation
  • -XX:TieredStopAtLevel=1
  • -noverify
  • -Djava.net.preferIPv4Stack=true
  • -jar

Puede proporcionar argumentos adicionales en una configuración con nombre de aplicación JAVA_OPTS.You can provide additional arguments in an app setting named JAVA_OPTS. Puede agregar la configuración de la aplicación para la aplicación de función que se implementó en Azure mediante una de estas maneras:You can add app settings to your function app deployed to Azure in one of these ways:

Azure PortalAzure portal

En el portal de Azure, utilice el ficha Configuración de la aplicación para agregar la JAVA_OPTS configuración.In the Azure portal, use the Application Settings tab to add the JAVA_OPTS setting.

Azure CLIAzure CLI

El az functionapp config appsettings set comando puede utilizarse para establecer JAVA_OPTS, como en el ejemplo siguiente:The az functionapp config appsettings set command can be used to set JAVA_OPTS, as in the following example:

```azurecli-interactive
az functionapp config appsettings set --name <APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings "JAVA_OPTS=-Djava.awt.headless=true"
```

Este ejemplo habilita el modo "desatendido".This example enables headless mode. Reemplace <APP_NAME> con el nombre de la aplicación de función y <RESOURCE_GROUP> con el grupo de recursos.Replace <APP_NAME> with the name of your function app and <RESOURCE_GROUP> with the resource group.

Advertencia

Cuando se ejecuta en un plan de consumo, debe agregar el WEBSITE_USE_PLACEHOLDER establecer con un valor de 0.When running in a Consumption plan, you must add the WEBSITE_USE_PLACEHOLDER setting with a value of 0.
Esta configuración de aumentar los tiempos de arranque en frío para las funciones de Java.This setting does increase the cold start times for Java functions.

Bibliotecas de tercerosThird-party libraries

Azure Functions admite el uso de bibliotecas de terceros.Azure Functions supports the use of third-party libraries. De forma predeterminada, todas las dependencias especificadas en el archivo pom.xml del proyecto se incluirán automáticamente durante el objetivo de mvn package.By default, all dependencies specified in your project pom.xml file will be automatically bundled during the mvn package goal. Para las bibliotecas no especificadas como dependencias en el archivo pom.xml, colóquelas en un directorio lib del directorio raíz de la función.For libraries not specified as dependencies in the pom.xml file, place them in a lib directory in the function's root directory. Las dependencias colocadas en el directorio lib se agregarán al cargador de clases del sistema en tiempo de ejecución.Dependencies placed in the lib directory will be added to the system class loader at runtime.

La dependencia com.microsoft.azure.functions:azure-functions-java-library se proporciona en la ruta de acceso de la clase de forma predeterminada y no deben incluirse en el directorio lib.The com.microsoft.azure.functions:azure-functions-java-library dependency is provided on the classpath by default, and does not need to be included in the lib directory. Asimismo, las dependencias que se enumeran aquí se agregan a la ruta de clase gracias a azure-functions-java-worker.Also, dependencies listed here are added to the classpath by azure-functions-java-worker.

Compatibilidad con los tipos de datosData type support

Puede usar objetos de Java POJO (Plain Old Java Object), tipos definidos en azure-functions-java-library o tipos de datos primitivos como String, Integer para enlazar con los enlaces de entrada o salida.You can use Plain old Java objects (POJOs), types defined in azure-functions-java-library or primitive dataTypes such as String, Integer to bind to input/output bindings.

Objetos POJOPlain old Java objects (POJOs)

Para convertir los datos de entrada a POJO, azure-functions-java-worker usa la biblioteca gson.For converting input data to POJO, azure-functions-java-worker uses gson library. Los tipos de POJO que se usan como entradas para las funciones deben ser public.POJO types used as inputs to functions should be public.

Datos binariosBinary data

Enlace entradas o salidas binarias a byte[]; para ello, establezca el campo dataType en function.json como binary:Bind binary inputs or outputs to byte[] by setting the dataType field in your function.json to binary:

   @FunctionName("BlobTrigger")
    @StorageAccount("AzureWebJobsStorage")
     public void blobTrigger(
        @BlobTrigger(name = "content", path = "myblob/{fileName}", dataType = "binary") byte[] content,
        @BindingName("fileName") String fileName,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java Blob trigger function processed a blob.\n Name: " + fileName + "\n Size: " + content.length + " Bytes");
    }

Use Optional<T> por si se esperan valores NULL.Use Optional<T> for if null values are expected

EnlacesBindings

Los enlaces de entrada y de salida permiten conectarse de manera declarativa a los datos desde el código.Input and output bindings provide a declarative way to connect to data from within your code. Cada función puede tener varios enlaces de entrada y de salida.A function can have multiple input and output bindings.

Ejemplo de un enlace de entradaExample Input binding

package com.example;

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

public class Function {
    @FunctionName("echo")
    public static String echo(
        @HttpTrigger(name = "req", methods = { "put" }, authLevel = AuthorizationLevel.ANONYMOUS, route = "items/{id}") String inputReq,
        @TableInput(name = "item", tableName = "items", partitionKey = "Example", rowKey = "{id}", connection = "AzureWebJobsStorage") TestInputData inputData
        @TableOutput(name = "myOutputTable", tableName = "Person", connection = "AzureWebJobsStorage") OutputBinding<Person> testOutputData,
    ) {
        testOutputData.setValue(new Person(httpbody + "Partition", httpbody + "Row", httpbody + "Name"));
        return "Hello, " + inputReq + " and " + inputData.getKey() + ".";
    }

    public static class TestInputData {
        public String getKey() { return this.RowKey; }
        private String RowKey;
    }
    public static class Person {
        public String PartitionKey;
        public String RowKey;
        public String Name;

        public Person(String p, String r, String n) {
            this.PartitionKey = p;
            this.RowKey = r;
            this.Name = n;
        }
    }
}

Esta función se invoca con una solicitud HTTP.This function is invoked with an HTTP request.

  • La carga útil de la solicitud HTTP se pasa como String para el argumento inputReq.HTTP request payload is passed as a String for the argument inputReq
  • Una entrada se recupera de Azure Table Storage y se pasa como TestInputData al argumento inputData.One entry is retrieved from the Azure Table Storage and is passed as TestInputData to the argument inputData.

Para recibir un lote de entradas, puede enlazar a String[], POJO[], List<String>, o List<POJO>.To receive a batch of inputs, you can bind to String[], POJO[], List<String>, or List<POJO>.

@FunctionName("ProcessIotMessages")
    public void processIotMessages(
        @EventHubTrigger(name = "message", eventHubName = "%AzureWebJobsEventHubPath%", connection = "AzureWebJobsEventHubSender", cardinality = Cardinality.MANY) List<TestEventData> messages,
        final ExecutionContext context)
    {
        context.getLogger().info("Java Event Hub trigger received messages. Batch size: " + messages.size());
    }
    
    public class TestEventData {
    public String id;
}

Esta función se desencadena cuando hay nuevos datos en el centro de eventos configurado.This function gets triggered whenever there is new data in the configured event hub. Como cardinality se establece en MANY, la función recibe un lote de mensajes desde el centro de eventos.As the cardinality is set to MANY, function receives a batch of messages from event hub. El elemento EventData del centro de eventos se convierte a TestEventData para la ejecución de la función.EventData from event hub gets converted to TestEventData for the function execution.

Ejemplo de enlace de salidaExample Output binding

Puede enlazar un enlace de salida al valor de retorno con $return.You can bind an output binding to the return value using $return

package com.example;

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

public class Function {
    @FunctionName("copy")
    @StorageAccount("AzureWebJobsStorage")
    @BlobOutput(name = "$return", path = "samples-output-java/{name}")
    public static String copy(@BlobTrigger(name = "blob", path = "samples-input-java/{name}") String content) {
        return content;
    }
}

Si hay varios enlaces de salida, use el valor devuelto para solo uno de ellos.If there are multiple output bindings, use the return value for only one of them.

Para enviar varios valores de salida, use el tipo OutputBinding<T> que se define en el paquete azure-functions-java-library.To send multiple output values, use OutputBinding<T> defined in the azure-functions-java-library package.

@FunctionName("QueueOutputPOJOList")
    public HttpResponseMessage QueueOutputPOJOList(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
            HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            @QueueOutput(name = "itemsOut", queueName = "test-output-java-pojo", connection = "AzureWebJobsStorage") OutputBinding<List<TestData>> itemsOut, 
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");
       
        String query = request.getQueryParameters().get("queueMessageId");
        String queueMessageId = request.getBody().orElse(query);
        itemsOut.setValue(new ArrayList<TestData>());
        if (queueMessageId != null) {
            TestData testData1 = new TestData();
            testData1.id = "msg1"+queueMessageId;
            TestData testData2 = new TestData();
            testData2.id = "msg2"+queueMessageId;

            itemsOut.getValue().add(testData1);
            itemsOut.getValue().add(testData2);

            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + queueMessageId).build();
        } else {
            return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("Did not find expected items in CosmosDB input list").build();
        }
    }

     public static class TestData {
        public String id;
    }

Esta función se invoca en un objeto HttpRequest y escribe varios valores en la cola de Azure.This function is invoked on an HttpRequest and writes multiple values to the Azure Queue.

HttpRequestMessage y HttpResponseMessageHttpRequestMessage and HttpResponseMessage

Los tipos HttpRequestMessage y HttpResponseMessage que se definen en azure-functions-java-library son tipos de ayuda que le permitirán trabajar con las funciones HttpTrigger.HttpRequestMessage and HttpResponseMessage types are defined in azure-functions-java-library are helper types to work with HttpTrigger functions

Tipo especializadoSpecialized Type DestinoTarget Uso típicoTypical Usage
HttpRequestMessage<T> Desencadenador HTTPHTTP Trigger Método get, encabezados o consultasGet method, headers, or queries
HttpResponseMessage Enlace de salida HTTPHTTP Output Binding Estado de retorno distinto de 200Return status other than 200

MetadatosMetadata

Algunos desencadenadores envían metadatos de desencadenador junto con datos de entrada.Few triggers send trigger metadata along with input data. Puede usar la anotación @BindingName para enlazarla a los metadatos de desencadenador.You can use annotation @BindingName to bind to trigger metadata

package com.example;

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


public class Function {
    @FunctionName("metadata")
    public static String metadata(
        @HttpTrigger(name = "req", methods = { "get", "post" }, authLevel = AuthorizationLevel.ANONYMOUS) Optional<String> body,
        @BindingName("name") String queryValue
    ) {
        return body.orElse(queryValue);
    }
}

En el ejemplo anterior, el elemento queryValue está enlazado al parámetro de cadena de consulta name de la dirección URL de solicitud de HTTP http://{example.host}/api/metadata?name=test.In the example above, the queryValue is bound to query string parameter name in the Http request URL http://{example.host}/api/metadata?name=test. A continuación, se muestra otro ejemplo para enlazarse a Id desde los metadatos de desencadenador de la cola.Following is another example to binding to Id from queue trigger metadata

 @FunctionName("QueueTriggerMetadata")
    public void QueueTriggerMetadata(
        @QueueTrigger(name = "message", queueName = "test-input-java-metadata", connection = "AzureWebJobsStorage") String message,@BindingName("Id") String metadataId,
        @QueueOutput(name = "output", queueName = "test-output-java-metadata", connection = "AzureWebJobsStorage") OutputBinding<TestData> output,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java Queue trigger function processed a message: " + message + " with metadaId:" + metadataId );
        TestData testData = new TestData();
        testData.id = metadataId;
        output.setValue(testData);
    }

Nota

El nombre que se proporciona en la anotación debe coincidir con la propiedad de metadatos.Name provided in the annotation needs to match the metadata property

Contexto de ejecuciónExecution context

El elemento ExecutionContext definido en azure-functions-java-library contiene métodos de ayuda que le permitirán comunicarse con las funciones en tiempo de ejecución.ExecutionContext defined in the azure-functions-java-library contains helper methods to communicate with the functions runtime.

RegistradorLogger

Use getLogger, que está definido en ExecutionContext, para escribir registros desde el código de función.Use getLogger defined in ExecutionContext to write logs from function code.

Ejemplo:Example:


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

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 by function " + context.getFunctionName() + " with invocation " + context.getInvocationId());
        }
        return String.format(req);
    }
}

Ver registros y seguimientoView logs and trace

Puede usar la CLI de Azure para hacer streaming del registro stdout y stderr de Java, así como de otros registros de la aplicación.You can use the Azure CLI to stream Java stdout and stderr logging as well as other application logging.

Configure la aplicación de función para escribir el registro de aplicación con la CLI de Azure:Configure your Function application to write application logging using the Azure CLI:

az webapp log config --name functionname --resource-group myResourceGroup --application-logging true

Para transmitir en secuencias la salida para la aplicación de función con la CLI de Azure, abra una nueva sesión del símbolo del sistema, Bash o Terminal y escriba el siguiente comando:To stream logging output for your Function app using the Azure CLI, open a new command prompt, Bash, or Terminal session and enter the following command:

az webapp log tail --name webappname --resource-group myResourceGroup

El comando az webapp log tail tiene opciones para filtrar la salida usando la opción --provider.The az webapp log tail command has options to filter output using the --provider option.

Para descargar los archivos de registro como un solo archivo ZIP mediante la CLI de Azure, abra una sesión nueva del símbolo del sistema, Bash o Terminal y escriba el siguiente comando:To download the log files as a single ZIP file using the Azure CLI, open a new command prompt, Bash, or Terminal session and enter the following command:

az webapp log download --resource-group resourcegroupname --name functionappname

Debe haber habilitado el sistema de archivos de registro en Azure portal o la CLI de Azure antes de ejecutar este comando.You must have enabled file system logging in the Azure portal or Azure CLI before running this command.

Variables de entornoEnvironment variables

En Functions, la configuración de la aplicación, como las cadenas de conexión del servicio, se exponen como variables de entorno durante la ejecución.In Functions, app settings, such as service connection strings, are exposed as environment variables during execution. Puede obtener acceso a estas opciones mediante, System.getenv("AzureWebJobsStorage").You can access these settings using, System.getenv("AzureWebJobsStorage")

Ejemplo:Example:

Agregue AppSetting con el nombre testAppSetting y el valor testAppSettingValue.Add AppSetting with name testAppSetting and value testAppSettingValue


public class Function {
    public String echo(@HttpTrigger(name = "req", methods = {"post"}, authLevel = AuthorizationLevel.ANONYMOUS) String req, ExecutionContext context) {
        context.getLogger().info("testAppSetting "+ System.getenv("testAppSettingValue"));
        return String.format(req);
    }
}

Pasos siguientesNext steps

Para obtener más información acerca del desarrollo de Java de Azure Fuctions, consulte los siguientes recursos:For more information about Azure Function Java development, see the following resources: