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

El tiempo de ejecución de Azure Functions admite Java SE 8 LTS (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 Java es un método public decorado con la anotación @FunctionName.A Java function is a public method, decorated with the annotation @FunctionName. Este método define la entrada de una función Java, y debe ser única en un paquete determinado.This method defines the entry for a Java function, and must be unique in a particular 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 Maven.You should also complete the Functions quickstart to create your first function, by using Visual Studio Code or 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 Azure Functions:Here is the folder structure of an Azure Functions 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

Puede usar un archivo host.json compartido para configurar la aplicación de funciones.You can use a shared host.json file 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. FunctionApp en el directorio de destino es lo que se implementa en la aplicación de funciones 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 se invocan mediante un desencadenador, como una solicitud HTTP, un temporizador o una actualización de datos.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 más información, vea los documentos de referencia de Java.For more information, see the Java reference docs.

Importante

Debe configurar una cuenta de Azure Storage en local.settings.json para ejecutar de manera local los desencadenadores de Azure Blob Storage, Azure Queue Storage o Azure Table Storage.You must configure an Azure Storage account in your local.settings.json to run Azure Blob storage, Azure Queue storage, or Azure Table storage 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

Para el desarrollo local de aplicaciones de funciones Java, descargue y utilice los JDK de Java 8 de Azul Zulu Enterprise for Azure de Azul Systems.For local development of Java function apps, download and use the Azul Zulu Enterprise for Azure Java 8 JDKs from Azul Systems. 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 funciones 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 Java (JVM) utilizada para ejecutar funciones Java.Functions lets you customize the Java virtual machine (JVM) used to run your Java functions. Las 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 de la aplicación denominada JAVA_OPTS.You can provide additional arguments in an app setting named JAVA_OPTS. Puede agregar la configuración de la aplicación a la aplicación de funciones implementada en Azure en Azure Portal o la CLI de Azure.You can add app settings to your function app deployed to Azure in the Azure portal or the Azure CLI.

Portal de AzureAzure portal

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

Azure CLIAzure CLI

Puede usar el comando az functionapp config appsettings set para establecer JAVA_OPTS, como en el siguiente ejemplo:You can use the az functionapp config appsettings set command to set JAVA_OPTS, as in the following example:

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

En este ejemplo se habilita el modo "desatendido".This example enables headless mode. Reemplace <APP_NAME> por el nombre de su aplicación de funciones y <RESOURCE_GROUP>, por el grupo de recursos.Replace <APP_NAME> with the name of your function app, and <RESOURCE_GROUP> with the resource group.

Advertencia

En Plan de consumo, debe agregar la configuración WEBSITE_USE_PLACEHOLDER con un valor de 0.In the Consumption plan, you must add the WEBSITE_USE_PLACEHOLDER setting with a value of 0.
Esta configuración aumenta los tiempos de arranque en frío de las funciones 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 incluyen automáticamente durante el objetivo de mvn package.By default, all dependencies specified in your project pom.xml file are 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 agregan al cargador de clases del sistema en tiempo de ejecución.Dependencies placed in the lib directory are 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 debe incluirse en el directorio lib.The com.microsoft.azure.functions:azure-functions-java-library dependency is provided on the classpath by default, and doesn't need to be included in the lib directory. Asimismo, azure-functions-java-worker agrega a la ruta de clase las dependencias que figuran aquí.Also, azure-functions-java-worker adds dependencies listed here to the classpath.

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 e Integer para enlazar con enlaces de entrada o salida.You can use Plain old Java objects (POJOs), types defined in azure-functions-java-library, or primitive data types such as String and Integer to bind to input or output bindings.

POJOPOJOs

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 the 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");
    }

Si espera valores null, use Optional<T>.If you expect null values, use Optional<T>.

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 enlace de entradaInput binding example

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.You invoke this function 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 Table Storage y se pasa como TestInputData al argumento inputData.One entry is retrieved from Table storage, and is passed as TestInputData to the argument inputData.

Para recibir un lote de entradas, puede enlazarse 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.Because the cardinality is set to MANY, the function receives a batch of messages from the 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 salidaOutput binding example

Puede enlazar un enlace de salida al valor de retorno con $return.You can bind an output binding to the return value by 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 una solicitud HttpRequest.You invoke this function on an HttpRequest. Escribe varios valores en Queue Storage.It writes multiple values to Queue storage.

HttpRequestMessage y HttpResponseMessageHttpRequestMessage and HttpResponseMessage

Se definen en azure-functions-java-library.These are defined in azure-functions-java-library. Son tipos de aplicación auxiliar que funcionan con funciones HttpTrigger.They are helper types to work with HttpTrigger functions.

Tipo especializadoSpecialized type DestinoTarget Uso típicoTypical usage
HttpRequestMessage<T> Desencadenador HTTPHTTP Trigger Obtiene el método, encabezados o consultas.Gets method, headers, or queries
HttpResponseMessage Enlace de salida HTTPHTTP Output Binding Devuelve un estado distinto de 200.Returns 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 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 HTTP http://{example.host}/api/metadata?name=test.In the preceding example, the queryValue is bound to the query string parameter name in the http request URL, http://{example.host}/api/metadata?name=test. Este es otro ejemplo que muestra cómo enlazar a Id desde los metadatos de desencadenador de la cola.Here's another example, showing how to bind 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.The 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 el elemento getLogger 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.

Aquí se explica cómo configurar la aplicación de funciones para escribir el registro de aplicación con la CLI de Azure:Here's how to configure your function app to write application logging by 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 funciones 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 by 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 by 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 by 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 registro del sistema de archivos 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 the 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 by using, System.getenv("AzureWebJobsStorage").

Por ejemplo, puede agregar AppSetting con el nombre testAppSetting y el valor testAppSettingValue:For example, you can add AppSetting, with the name testAppSetting and the 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 más información sobre el desarrollo de Java de Azure Functions, vea los siguientes recursos:For more information about Azure Functions Java development, see the following resources: