Spring Cloud Function in Azure

Questo articolo illustra come compilare, testare, eseguire il debug e distribuire una funzione Spring Cloud Java in Funzioni di Azure. Al termine, la funzione viene eseguita nel piano a consumo e risponde alle richieste HTTP.

Prerequisiti

Per sviluppare funzioni usando Java, installare gli strumenti seguenti:

Importante

Imposta la variabile di ambiente JAVA_HOME sul percorso di installazione del JDK per completare questa guida rapida.

Verificare che la versione degli strumenti di base sia almeno 4.0.5455.

Quello che si intende costruire

Si creerà una funzione classica "Hello, World" che viene eseguita in Funzioni di Azure ed è configurata con Spring Cloud Function.

La funzione riceve un User oggetto JSON che contiene un nome utente e restituisce un Greeting oggetto che contiene il messaggio di benvenuto per l'utente.

Il progetto è disponibile nell'esempio Spring Cloud Function in Azure del azure-function-java-worker repository su GitHub. È possibile usare questo esempio direttamente se si vuole visualizzare il lavoro finale descritto in questa guida introduttiva.

Creare un nuovo progetto Maven

Creare un progetto Maven vuoto e configurarlo con Spring Cloud Function e Funzioni di Azure.

In una cartella vuota creare un nuovo file pom.xml . Copiare quindi il contenuto dal file dipom.xml del progetto di esempio.

Nota

Questo file usa le dipendenze Maven sia da Spring Boot che da Spring Cloud Function. Configura anche i plug-in Spring Boot e Funzioni di Azure Maven.

Personalizzare alcune proprietà per l'applicazione:

  • <functionAppName>è il nome della funzione Azure.
  • <functionAppRegion>è il nome dell'area Azure in cui si distribuisce la funzione.
  • <functionResourceGroup>è il nome del gruppo di risorse Azure in uso.

Modificare queste proprietà direttamente nella parte superiore del file pom.xml , come illustrato nell'esempio seguente:

    <properties>
        <java.version>11</java.version>

        <!-- Spring Boot start class. WARNING: correct class must be set -->
        <start-class>com.example.DemoApplication</start-class>

        <!-- customize those properties. WARNING: the functionAppName should be unique across Azure -->
        <azure.functions.maven.plugin.version>1.36.0</azure.functions.maven.plugin.version>
        <functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
        <functionAppServicePlanName>my-spring-function-service-plan</functionAppServicePlanName>
        <functionAppName>my-spring-function</functionAppName>
        <functionPricingTier>Y1</functionPricingTier>
        <functionAppRegion>eastus</functionAppRegion>
    </properties>

Creare i file di configurazione di Azure

Creare una cartella src/main/resources e aggiungervi i seguenti file di configurazione di Funzioni di Azure.

host.json:

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.2.0)"
  },
  "functionTimeout": "00:10:00"
}

local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "java",
    "FUNCTIONS_EXTENSION_VERSION": "~4",
    "AzureWebJobsDashboard": ""
  }
}

Creare gli oggetti di dominio

Funzioni di Azure può ricevere e inviare oggetti in formato JSON. Creare User oggetti e Greeting che rappresentano il modello di dominio. Se si vuole personalizzare questa guida introduttiva, è possibile creare oggetti più complessi con più proprietà.

Creare una cartella src/main/java/com/example/model e aggiungere i due file seguenti:

User.java:

package com.example.model;

public class User {

    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Greeting.java:

package com.example.model;

public class Greeting {

    private String message;

    public Greeting() {
    }

    public Greeting(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Creare l'applicazione Spring Boot

Questa applicazione gestisce tutta la logica di business e ha accesso all'ecosistema Spring Boot completo. Questa funzionalità offre due vantaggi principali rispetto a una funzione di Azure standard:

  • Non si basa sulle API Funzioni di Azure, quindi è possibile convertirla facilmente in altri sistemi. Ad esempio, è possibile riutilizzarlo in una normale applicazione Spring Boot.
  • È possibile usare tutte le @Enable annotazioni di Spring Boot per aggiungere nuove funzionalità.

Nella cartella src/main/java/com/example creare il file seguente, che è una normale applicazione Spring Boot:

DemoApplication.java:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Creare ora il file seguente nella cartella src/main/java/com/example/hello . Questo codice contiene un componente Spring Boot che rappresenta la funzione da eseguire:

Hello.java:

package com.example.hello;

import com.example.model.*;
import org.springframework.stereotype.Component;
import java.util.function.Function;

@Component
public class Hello implements Function<User, Greeting> {

    @Override
    public Greeting apply(User user) {
        return new Greeting("Hello, " + user.getName() + "!\n");
    }
}

Nota

La funzione Hello è piuttosto specifica:

  • È un java.util.function.Function. Contiene la logica di business e usa un'API Java standard per trasformare un oggetto in un altro.
  • Poiché ha l'annotazione @Component, è un bean Spring. Per impostazione predefinita, il nome corrisponde alla classe , ma inizia con un carattere minuscolo: hello. Se si vuole creare altre funzioni nell'applicazione, seguire questa convenzione di denominazione è importante. Il nome deve corrispondere al nome Funzioni di Azure creato nella sezione successiva.

Creare la funzione di Azure

Per usare l'API Funzioni di Azure completa, creare una funzione Azure che delega l'esecuzione alla funzione Spring Cloud creata nel passaggio precedente.

Nella cartella src/main/java/com/example/hello creare il file di classe della funzione di Azure seguente:

HelloHandler.java:

package com.example.hello;

import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import com.example.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class HelloHandler {

    @Autowired
    private Hello hello;

    @FunctionName("hello")
    public HttpResponseMessage execute(
        @HttpTrigger(name = "request", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request, ExecutionContext context) {
        User user = request.getBody()
                           .filter(u -> u.getName() != null)
                           .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world")));
        context.getLogger().info("Greeting user name: " + user.getName());
        return request.createResponseBuilder(HttpStatus.OK)
                      .body(hello.apply(user))
                      .header("Content-Type", "application/json")
                      .build();
    }
}

Questa classe Java è una funzione Azure con le funzionalità seguenti:

  • La classe ha l'annotazione @Component, quindi è un Spring Bean.
  • Il nome della funzione, come definito dall'annotazione @FunctionName("hello") , è hello.
  • La classe implementa una funzione di Azure reale, quindi è possibile usare l'API Funzioni di Azure completa qui.

Aggiungere test unitari

Questo passaggio è facoltativo, ma consigliato per verificare che l'applicazione funzioni correttamente.

Creare una cartella src/test/java/com/example e aggiungere i test JUnit seguenti:

HelloTest.java:

package com.example;

import com.example.hello.Hello;
import com.example.model.Greeting;
import com.example.model.User;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class HelloTest {

    @Test
    public void test() {
        Greeting result = new Hello().apply(new User("foo"));
        assertThat(result.getMessage()).isEqualTo("Hello, foo!\n");
    }
}

È ora possibile testare la funzione Azure usando Maven:

mvn clean test

Eseguire la funzione in locale

Prima di distribuire l'applicazione in Azure Funzione, testarla in locale.

In primo luogo, creare un pacchetto dell'applicazione in un file JAR:

mvn package

Ora che l'applicazione è in pacchetto, eseguirla usando il plug-in azure-functions Maven:

mvn azure-functions:run

La funzione Azure è ora disponibile in localhost, usando la porta 7071. Testare la funzione inviando una richiesta POST, con un User oggetto in formato JSON. Ad esempio, usare cURL:

curl -X POST http://localhost:7071/api/hello -d "{\"name\":\"Azure\"}"

La funzione risponde con un Greeting oggetto, in formato JSON:

{
  "message": "Hello, Azure!\n"
}

Ecco uno screenshot della richiesta cURL nella parte superiore della schermata e della funzione di Azure locale nella parte inferiore:

Esecuzione in locale della funzione di Azure

Eseguire il debug della funzione in locale

Le sezioni seguenti descrivono come eseguire il debug della funzione.

Eseguire il debug con Intellij IDEA

Aprire il progetto in IntelliJ IDEA e quindi creare una configurazione di esecuzione di debug JVM remota da collegare. Per altre informazioni, vedere Esercitazione: Debug remoto.

Creare una configurazione di esecuzione di debug JVM remota

Eseguire l'applicazione con il comando seguente:

mvn azure-functions:run -DenableDebug

All'avvio dell'applicazione viene visualizzato l'output seguente:

Worker process started and initialized.
Listening for transport dt_socket at address: 5005

Avviare il debug del progetto in IntelliJ IDEA. Viene visualizzato l'output seguente:

Connected to the target VM, address: 'localhost:5005', transport: 'socket'

Contrassegnare i punti di interruzione di cui si vuole eseguire il debug. IntelliJ IDEA passa alla modalità di debug dopo l'invio di una richiesta.

Eseguire il debug con Visual Studio Code

Aprire il progetto in Visual Studio Code e quindi configurare il contenuto del file dilaunch.json seguente:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "java",
            "name": "Attach to Remote Program",
            "request": "attach",
            "hostName": "127.0.0.1",
            "port": 5005
        }
    ]
}

Eseguire l'applicazione con il comando seguente:

mvn azure-functions:run -DenableDebug

All'avvio dell'applicazione viene visualizzato l'output seguente:

Worker process started and initialized.
Listening for transport dt_socket at address: 5005

Avviare il debug del progetto in Visual Studio Code e quindi contrassegnare i punti di interruzione di cui si vuole eseguire il debug. Visual Studio Code passa alla modalità di debug dopo l'invio di una richiesta. Per altre informazioni, vedere Esecuzione e debug di Java.

Distribuire la funzione in Funzioni di Azure

Si pubblicherà ora la funzione di Azure nell'ambiente di produzione. Tenere presente che le <functionAppName>proprietà , <functionAppRegion>e <functionResourceGroup> definite nel file pom.xml vengono usate per configurare la funzione.

Nota

Il plug-in Maven deve eseguire l'autenticazione con Azure. Se è installata l'interfaccia della riga di comando di Azure, usare az login prima di continuare.

Per altre opzioni di autenticazione, vedere Autenticazione nel azure-maven-plugins repository.

Esegui Maven per distribuire automaticamente la tua funzione:

mvn azure-functions:deploy

Ora vai al portale di Azure per trovare il Function App che è stato creato.

Selezionare la funzione :

  • Nella panoramica della funzione prendere nota del relativo URL.
  • Per controllare la funzione in esecuzione, selezionare Flusso di log nel menu di navigazione.

Come è stato fatto nella sezione precedente, usare cURL per accedere alla funzione in esecuzione, come illustrato nell'esempio seguente. Assicurarsi di sostituire your-function-name con il nome della funzione reale.

curl https://your-function-name.azurewebsites.net/api/hello -d "{\"name\":\"Azure\"}"

Come nella sezione precedente, la funzione dovrebbe rispondere con un oggetto Greeting, sempre in formato JSON:

{
  "message": "Hello, Azure!\n"
}

Congratulazioni, hai una funzione Spring Cloud in esecuzione su Funzioni di Azure! Per altre informazioni ed esempi di funzioni spring cloud, vedere le risorse seguenti:

Passaggi successivi

Per altre informazioni su Spring e Azure, passare al centro di documentazione di Spring in Azure.