Criar sua primeira função durável em Java

Durable Functions são uma extensão do Azure Functions que permitem que você escreva funções com estado em um ambiente sem servidor. A extensão gerencia estado, pontos de verificação e reinicializações para você.

Neste guia de início rápido, você aprenderá a criar e testar um aplicativo Durable Functions "Olá, Mundo" em Java. O aplicativo Durable Functions mais básico contém as três seguintes funções:

  • Função de orquestrador – descreve um fluxo de trabalho que orquestra outras funções.
  • Função de atividade – chamada pela função de orquestrador, executa o trabalho e, opcionalmente, retorna um valor.
  • Função de cliente – uma Função do Azure regular que inicia uma função de orquestrador. Este exemplo usa uma função disparada por HTTP.

Este guia de início rápido mostrará como criar esse aplicativo "Olá, Mundo", que você poderá fazer de diferentes maneiras. Use o seletor acima para escolher sua abordagem preferida.

Pré-requisitos

Para concluir este tutorial, você precisará:

  • O Java Developer Kit, versão 8 ou mais recente.

  • O Apache Maven, versão 3.0 ou mais recente.

  • A versão mais recente do Azure Functions Core Tools.

    • Para o Azure Functions 4.x, o Core Tools v4.0.4915 ou mais recentes é necessário.
  • Uma conta Armazenamento do Azure, que exige que você tenha uma assinatura do Azure.

Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.

Adicionar as dependências e os plug-ins necessários ao projeto

Adicione os itens a seguir a sua pom.xml:

<properties>
  <azure.functions.maven.plugin.version>1.18.0</azure.functions.maven.plugin.version>
  <azure.functions.java.library.version>3.0.0</azure.functions.java.library.version>
  <durabletask.azure.functions>1.0.0</durabletask.azure.functions>
  <functionAppName>your-unique-app-name</functionAppName>
</properties>

<dependencies>
  <dependency>
    <groupId>com.microsoft.azure.functions</groupId>
    <artifactId>azure-functions-java-library</artifactId>
    <version>${azure.functions.java.library.version}</version>
  </dependency>
  <dependency>
    <groupId>com.microsoft</groupId>
    <artifactId>durabletask-azure-functions</artifactId>
    <version>${durabletask.azure.functions}</version>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
    </plugin>
    <plugin>
      <groupId>com.microsoft.azure</groupId>
      <artifactId>azure-functions-maven-plugin</artifactId>
      <version>${azure.functions.maven.plugin.version}</version>
      <configuration>
        <appName>${functionAppName}</appName>
        <resourceGroup>java-functions-group</resourceGroup>
        <appServicePlanName>java-functions-app-service-plan</appServicePlanName>
        <region>westus</region>
        <runtime>
          <os>windows</os>
          <javaVersion>11</javaVersion>
        </runtime>
        <appSettings>
          <property>
            <name>FUNCTIONS_EXTENSION_VERSION</name>
            <value>~4</value>
          </property>
        </appSettings>
      </configuration>
      <executions>
        <execution>
          <id>package-functions</id>
          <goals>
            <goal>package</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <artifactId>maven-clean-plugin</artifactId>
      <version>3.1.0</version>
    </plugin>
  </plugins>
</build>

Adicionar arquivos JSON necessários

Adicionar um arquivo host.json ao seu diretório de projeto. Ela deve parecer com o seguinte:

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "DurableTask.AzureStorage": "Warning",
      "DurableTask.Core": "Warning"
    }
  },
  "extensions": {
    "durableTask": {
      "hubName": "JavaTestHub"
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

Observação

É importante observar que apenas o pacote de extensões do Azure Functions v4 tem o suporte necessário atualmente para as Durable Functions para Java. Não há suporte para as Durable Functions para Java em pacotes de extensões da v3 e anterior. Para obter mais informações sobre os pacotes de extensões, confira a documentação dos pacotes de extensões.

As Durable Functions precisam ter um provedor de armazenamento para armazenar o estado de runtime. Adicione um arquivo local.settings.json ao diretório do projeto para configurar o provedor de armazenamento. Para usar o Armazenamento do Azure como provedor, defina o valor de AzureWebJobsStorage como a cadeia de conexão da sua conta do Armazenamento do Azure:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "<your storage account connection string>",
    "FUNCTIONS_WORKER_RUNTIME": "java"
  }
}

Criar suas funções

O código de exemplo abaixo mostra um exemplo simples de cada um:

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

import com.microsoft.durabletask.*;
import com.microsoft.durabletask.azurefunctions.DurableActivityTrigger;
import com.microsoft.durabletask.azurefunctions.DurableClientContext;
import com.microsoft.durabletask.azurefunctions.DurableClientInput;
import com.microsoft.durabletask.azurefunctions.DurableOrchestrationTrigger;

public class DurableFunctionsSample {
    /**
     * This HTTP-triggered function starts the orchestration.
     */
    @FunctionName("StartOrchestration")
    public HttpResponseMessage startOrchestration(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            @DurableClientInput(name = "durableContext") DurableClientContext durableContext,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        DurableTaskClient client = durableContext.getClient();
        String instanceId = client.scheduleNewOrchestrationInstance("Cities");
        context.getLogger().info("Created new Java orchestration with instance ID = " + instanceId);
        return durableContext.createCheckStatusResponse(request, instanceId);
    }

    /**
     * This is the orchestrator function, which can schedule activity functions, create durable timers,
     * or wait for external events in a way that's completely fault-tolerant.
     */
    @FunctionName("Cities")
    public String citiesOrchestrator(
            @DurableOrchestrationTrigger(name = "taskOrchestrationContext") TaskOrchestrationContext ctx) {
        String result = "";
        result += ctx.callActivity("Capitalize", "Tokyo", String.class).await() + ", ";
        result += ctx.callActivity("Capitalize", "London", String.class).await() + ", ";
        result += ctx.callActivity("Capitalize", "Seattle", String.class).await() + ", ";
        result += ctx.callActivity("Capitalize", "Austin", String.class).await();
        return result;
    }

    /**
     * This is the activity function that gets invoked by the orchestrator function.
     */
    @FunctionName("Capitalize")
    public String capitalize(@DurableActivityTrigger(name = "name") String name, final ExecutionContext context) {
        context.getLogger().info("Capitalizing: " + name);
        return name.toUpperCase();
    }
}

Criar um projeto local com um comando do Maven

  1. Execute o seguinte comando para gerar um projeto com as funções básicas de um aplicativo Durable Functions:
mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DarchetypeVersion=1.51 -Dtrigger=durablefunctions
  1. Siga os avisos e forneça as seguintes informações:
Prompt Valor
groupId com.function
artifactId myDurableFunction
version 1.0-SNAPSHOT
package com.function
S Insira ENTER para confirmar

Agora você tem um projeto local gerado com as três funções necessárias para um aplicativo Durable Functions básico.

Verifique se você tem com.microsoft:durabletask-azure-functions como uma dependência no pom.xml.

Configurar o provedor de armazenamento de back-end

As Durable Functions precisam ter um provedor de armazenamento para armazenar o estado de runtime. Você pode configurar para usar o Armazenamento do Azure como o provedor de armazenamento em local.settings.json fornecendo a cadeia de conexão da sua conta do Armazenamento do Azure como o valor para AzureWebJobsStorage:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "<your storage account connection string>",
    "FUNCTIONS_WORKER_RUNTIME": "java"
  }
}

Criar seu projeto local

  1. No Visual Studio Code, pressione F1 (ou Ctrl/Cmd+Shift+P) para abrir a paleta de comandos. Na paleta de comandos, pesquise e selecione Azure Functions: Create New Project....

    Screenshot of create new functions project.

  2. Escolha um local em uma pasta vazia para o projeto e escolha Selecionar.

  3. Siga os avisos e forneça as seguintes informações:

    Prompt Valor
    Selecionar um idioma Escolha Java.
    Selecione uma versão do Java Escolha Java 8 ou mais recente, a versão do Java em que as funções são executadas no Azure. Escolha uma versão do Java verificada localmente.
    Forneça uma ID de grupo com.function.
    Forneça uma ID de artefato myDurableFunction.
    Forneça uma versão 1.0-SNAPSHOT.
    Forneça um nome de pacote com.function.
    Forneça um nome de aplicativo myDurableFunction.
    Selecione a ferramenta de build para o projeto Java Escolha Maven.
    Selecione como deseja abrir o projeto Escolha Open in new window.

Agora você tem um projeto com uma função HTTP de exemplo. Você poderá remover essa função se desejar, pois adicionaremos as funções básicas de um aplicativo Durable Functions na próxima etapa.

Adicionar funções ao projeto

  1. Na paleta de comandos, pesquise e selecione Azure Functions: Create Function....

  2. Selecione Change template filter para All.

  3. Siga os avisos e forneça as seguintes informações:

    Prompt Valor
    Selecione um modelo para a função DurableFunctionsOrchestration
    Forneça um nome de pacote com.function
    Forneça um nome de função DurableFunctionsOrchestrator
  4. Escolha Select storage account na janela pop-up solicitando a configuração das informações da conta de armazenamento e siga os prompts.

Agora você tem as três funções básicas geradas de um aplicativo Durable Functions.

Configurar o pom.xml e o host.json

Adicione a seguinte dependência ao pom.xml:

<dependency>
  <groupId>com.microsoft</groupId>
  <artifactId>durabletask-azure-functions</artifactId>
  <version>1.0.0</version>
</dependency>

Adicione a propriedade extensions ao host.json:

"extensions": { "durableTask": { "hubName": "JavaTestHub" }}

Testar a função localmente

As Ferramentas Principais do Azure Functions permitem executar um projeto do Azure Functions no seu computador de desenvolvimento local.

Observação

As Durable Functions para Java exigem o Azure Functions Core Tools v4.0.4915 ou mais recente. Você pode ver a versão instalada executando o comando func --version no terminal.

  1. Se você estiver usando o Visual Studio Code, abra uma nova janela de terminal e execute os seguintes comandos para criar o projeto:

    mvn clean package
    

    Em seguida, execute a função durável:

    mvn azure-functions:run
    
  2. No painel Terminal, copie o ponto de extremidade de URL da sua função disparada por HTTP.

    Screenshot of Azure local output.

  3. Usando uma ferramenta como Postman ou cURL, envie uma solicitação HTTP POST para o ponto de extremidade de URL. Você obterá uma resposta semelhante à seguinte:

    {
        "id": "d1b33a60-333f-4d6e-9ade-17a7020562a9",
        "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d1b33a60-333f-4d6e-9ade-17a7020562a9?code=ACCupah_QfGKoFXydcOHH9ffcnYPqjkddSawzRjpp1PQAzFueJ2tDw==",
        "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d1b33a60-333f-4d6e-9ade-17a7020562a9/raiseEvent/{eventName}?code=ACCupah_QfGKoFXydcOHH9ffcnYPqjkddSawzRjpp1PQAzFueJ2tDw==",
        "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d1b33a60-333f-4d6e-9ade-17a7020562a9?code=ACCupah_QfGKoFXydcOHH9ffcnYPqjkddSawzRjpp1PQAzFueJ2tDw==",
        "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d1b33a60-333f-4d6e-9ade-17a7020562a9/terminate?reason={text}&code=ACCupah_QfGKoFXydcOHH9ffcnYPqjkddSawzRjpp1PQAzFueJ2tDw=="
    }
    

    A resposta é o resultado inicial da função HTTP informando que a orquestração durável foi iniciada com êxito. A resposta ainda não é o resultado final da orquestração. A resposta inclui algumas URLs úteis. Por enquanto, vamos consultar o status da orquestração.

  4. Copie o valor da URL para statusQueryGetUri e cole-o na barra de endereços do navegador e execute a solicitação. Como alternativa, você também pode continuar usando o Postman ou o cURL para emitir a solicitação GET.

    A solicitação consultará a instância de orquestração do status. Você deve obter uma resposta eventual, que nos mostra que a instância foi concluída e inclui as saídas ou os resultados da função durável. Ele tem esta aparência:

    {
        "name": "Cities",
        "instanceId": "d1b33a60-333f-4d6e-9ade-17a7020562a9",
        "runtimeStatus": "Completed",
        "input": null,
        "customStatus": "",
        "output":"TOKYO, LONDON, SEATTLE, AUSTIN",
        "createdTime": "2022-12-12T05:00:02Z",
        "lastUpdatedTime": "2022-12-12T05:00:06Z"
    }