Partager via


Spring Cloud Function dans Azure

Cet article vous guide tout au long de l’utilisation de Spring Cloud Functions pour développer une fonction Java et la publier sur Azure Functions. Lorsque vous avez terminé, votre code de fonction s’exécute sur le plan de consommation dans Azure et peut être déclenché à l’aide d’une requête HTTP.

Conditions préalables

  • Un abonnement Azure. Si vous n’avez pas d’abonnement Azure , créez un compte gratuit avant de commencer.

Pour développer des fonctions à l’aide de Java, vous devez avoir installé les éléments suivants :

Important

  1. Vous devez définir la variable d’environnement JAVA_HOME sur l’emplacement d’installation du JDK pour suivre ce guide de démarrage rapide.
  2. Vérifiez que la version de vos outils de base est au moins 4.0.5455.

Ce que nous allons créer

Nous allons créer une fonction classique « Hello, World » qui s’exécute sur Azure Functions et qui est configurée avec Spring Cloud Function.

La fonction reçoit un objet JSON User, qui contient un nom d’utilisateur et renvoie un objet Greeting, qui contient le message d’accueil à cet utilisateur.

Le projet est disponible dans l’exemple Spring Cloud Function dans Azure du référentiel azure-function-java-worker sur GitHub. Vous pouvez utiliser cet exemple directement si vous souhaitez voir le travail final décrit dans ce guide de démarrage rapide.

Créer un projet Maven

Nous allons créer un projet Maven vide et le configurer avec Spring Cloud Function et Azure Functions.

Dans un dossier vide, créez un fichier pom.xml et copiez/collez le contenu à partir du fichier pom.xml de l’exemple de projet.

Remarque

Ce fichier utilise des dépendances Maven à partir de Spring Boot et de Spring Cloud Function, et configure les plug-ins Spring Boot et Azure Functions Maven.

Vous devez personnaliser quelques propriétés pour votre application :

  • <functionAppName> est le nom de votre fonction Azure
  • <functionAppRegion> est le nom de la région Azure où votre fonction est déployée
  • <functionResourceGroup> est le nom du groupe de ressources Azure que vous utilisez

Modifiez ces propriétés directement en haut du fichier pom.xml, comme indiqué dans l’exemple suivant :

    <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>

Créer des fichiers de configuration Azure

Créez un dossier src/main/resources et ajoutez-y les fichiers de configuration Azure Functions suivants.

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": ""
  }
}

Créer des objets de domaine

Azure Functions peut recevoir et envoyer des objets au format JSON. Nous allons maintenant créer nos objets User et Greeting, qui représentent notre modèle de domaine. Vous pouvez créer des objets plus complexes, avec plus de propriétés, si vous souhaitez personnaliser ce guide de démarrage rapide et le rendre plus intéressant pour vous.

Créez un dossier src/main/java/com/example/model et ajoutez les deux fichiers suivants :

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;
    }
}

Créer l’application Spring Boot

Cette application gère toute la logique métier et a accès à l’écosystème Spring Boot complet. Cette fonctionnalité offre deux avantages principaux sur une fonction Azure standard :

  • Il ne s’appuie pas sur les API Azure Functions. Vous pouvez donc facilement le porter vers d’autres systèmes. Par exemple, vous pouvez la réutiliser dans une application Spring Boot normale.
  • Vous pouvez utiliser toutes les annotations @Enable de Spring Boot pour ajouter de nouvelles fonctionnalités.

Dans le dossier src/main/java/com/example, créez le fichier suivant, qui est une application Spring Boot normale :

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

Créez maintenant le fichier suivant dans le dossier src/main/java/com/example/hello. Ce code contient un composant Spring Boot qui représente la fonction que nous voulons exécuter :

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

Remarque

La fonction Hello est assez spécifique :

  • Il s’agit d’une java.util.function.Function. Il contient la logique métier et utilise une API Java standard pour transformer un objet en un autre.
  • Comme il a l’annotation @Component, il s’agit d’un Spring Bean, et par défaut son nom est identique à la classe, mais en commençant par un caractère minuscule : hello. Suivre cette convention de nommage est important si vous souhaitez créer d'autres fonctions dans votre application. Le nom doit correspondre au nom Azure Functions que nous allons créer dans la section suivante.

Créer la fonction Azure

Pour tirer parti de l’API Azure Functions complète, nous codeons maintenant une fonction Azure qui délègue son exécution à la fonction Spring Cloud créée à l’étape précédente.

Dans le dossier src/main/java/com/example/hello, créez le fichier de classe de fonction Azure suivant :

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();
    }
}

Cette classe Java est une fonction Azure, avec les fonctionnalités intéressantes suivantes :

  • La classe a l’annotation @Component, donc c’est un Bean Spring.
  • Le nom de la fonction, tel que défini par l’annotation @FunctionName("hello"), est hello.
  • La classe implémente une vraie fonction Azure. Vous pouvez donc utiliser l’API Azure Functions complète ici.

Ajouter des tests unitaires

Cette étape est facultative, mais recommandée pour vérifier que l’application fonctionne correctement.

Créez un dossier src/test/java/com/example et ajoutez les tests JUnit suivants :

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

Vous pouvez maintenant tester votre fonction Azure à l’aide de Maven :

mvn clean test

Exécuter la fonction localement

Avant de déployer votre application sur Azure Function, nous allons d’abord la tester localement.

Tout d’abord, vous devez empaqueter votre application dans un fichier Jar :

mvn package

Maintenant que l’application est empaquetée, vous pouvez l’exécuter à l’aide du plug-in Maven azure-functions :

mvn azure-functions:run

La fonction Azure doit maintenant être disponible sur votre localhost, à l’aide du port 7071. Vous pouvez tester la fonction en l’envoyant une requête POST, avec un objet User au format JSON. Par exemple, à l’aide de cURL :

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

La fonction doit vous répondre avec un objet Greeting, toujours au format JSON :

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

Voici une capture d’écran de la requête cURL en haut de l’écran et de la fonction Azure locale en bas :

fonction Azure s’exécutant localement

Déboguer la fonction localement

Les sections suivantes décrivent comment déboguer la fonction.

Déboguer à l’aide d’Intellij IDEA

Ouvrez le projet dans IntelliJ IDEA, puis créez une configuration d’exécution Remote JVM Debug à attacher. Pour plus d’informations, consultez le tutoriel sur le débogage distant.

Créer une configuration d’exécution Remote JVM Debug

Exécutez l’application avec la commande suivante :

mvn azure-functions:run -DenableDebug

Au démarrage de l’application, la sortie suivante s’affiche :

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

Démarrez le débogage de projet dans IntelliJ IDEA. Vous voyez la sortie suivante :

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

Marquez les points d’arrêt que vous souhaitez déboguer. Intellij IDEA entre en mode débogage après l’envoi d’une demande.

Déboguer à l’aide de Visual Studio Code

Ouvrez le projet dans Visual Studio Code, puis configurez le contenu de fichier launch.json suivant :

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

Exécutez l’application avec la commande suivante :

mvn azure-functions:run -DenableDebug

Au démarrage de l’application, la sortie suivante s’affiche :

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

Commencez le débogage du projet dans Visual Studio Code, puis marquez les points d’arrêt que vous souhaitez examiner. Visual Studio Code entre en mode débogage après l’envoi d’une demande. Pour plus d’informations, consultez Exécution et débogage de Java.

Déployer la fonction sur Azure Functions

À présent, vous allez publier la fonction Azure en production. N’oubliez pas que les propriétés <functionAppName>, <functionAppRegion>et <functionResourceGroup> que vous avez définies dans votre fichier pom.xml sont utilisées pour configurer votre fonction.

Remarque

Le plug-in Maven doit s’authentifier auprès d’Azure. Si Azure CLI est installé, utilisez az login avant de continuer. Pour plus d’options d’authentification, consultez Authentication dans le référentiel azure-maven-plugins.

Exécutez Maven pour déployer automatiquement votre fonction :

mvn azure-functions:deploy

Accédez maintenant au portail Azure pour rechercher l’Function App qui a été créée.

Sélectionnez la fonction :

  • Dans la vue d’ensemble de la fonction, notez l’URL de la fonction.
  • Pour vérifier votre fonction en cours d’exécution, sélectionnez Diffusion des journaux dans le menu de navigation.

À présent, comme vous l’avez fait dans la section précédente, utilisez cURL pour accéder à la fonction en cours d’exécution, comme illustré dans l’exemple suivant. Veillez à remplacer your-function-name par votre nom de fonction réel.

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

Comme dans la section précédente, la fonction doit vous répondre avec un objet Greeting, toujours au format JSON :

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

Félicitations, vous avez une fonction Spring Cloud en cours d’exécution sur Azure Functions ! Pour plus d’informations et des exemples de fonctions Spring Cloud, consultez les ressources suivantes :

Étapes suivantes

Pour en savoir plus sur Spring et Azure, passez au centre de documentation Spring sur Azure.