6.4. Développer les fonctions de Quarkus


Après avoir créé un projet de fonction Quarkus, vous pouvez modifier les fichiers modèles fournis pour ajouter une logique commerciale à votre fonction. Cela inclut la configuration de l'invocation de la fonction et des en-têtes et codes d'état renvoyés.

6.4.1. Conditions préalables

6.4.2. Structure du modèle de fonction Quarkus

Lorsque vous créez une fonction Quarkus en utilisant la CLI Knative (kn), le répertoire du projet ressemble à un projet Maven typique. En outre, le projet contient le fichier func.yaml, qui est utilisé pour configurer la fonction.

Les fonctions de déclenchement http et event ont la même structure de modèle :

Structure du modèle

.
├── func.yaml 1
├── mvnw
├── mvnw.cmd
├── pom.xml 2
├── README.md
└── src
    ├── main
    │   ├── java
    │   │   └── functions
    │   │       ├── Function.java 3
    │   │       ├── Input.java
    │   │       └── Output.java
    │   └── resources
    │       └── application.properties
    └── test
        └── java
            └── functions 4
                ├── FunctionTest.java
                └── NativeFunctionIT.java

1
Utilisé pour déterminer le nom et le registre de l'image.
2
Le fichier POM (Project Object Model) contient la configuration du projet, notamment des informations sur les dépendances. Vous pouvez ajouter des dépendances supplémentaires en modifiant ce fichier.

Exemple de dépendances supplémentaires

...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>3.8.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
...

Les dépendances sont téléchargées lors de la première compilation.

3
Le projet de fonction doit contenir une méthode Java annotée avec @Funq. Vous pouvez placer cette méthode dans la classe Function.java.
4
Contient des cas de test simples qui peuvent être utilisés pour tester votre fonction localement.

6.4.3. A propos de l'invocation des fonctions de Quarkus

Vous pouvez créer un projet Quarkus qui répond aux événements cloud ou qui répond à de simples requêtes HTTP. Dans Knative, les événements cloud sont transportés par HTTP sous la forme d'une requête POST, de sorte que les deux types de fonctions peuvent écouter et répondre aux requêtes HTTP entrantes.

Lorsqu'une demande est reçue, les fonctions Quarkus sont invoquées avec une instance d'un type autorisé.

Tableau 6.1. Options d'invocation des fonctions
Méthode d'invocationType de données contenu dans l'instanceExemple de données

Demande HTTP POST

Objet JSON dans le corps de la demande

{ "customerId": "0123456", "productId": "6543210" }

Demande HTTP GET

Données dans la chaîne de requête

?customerId=0123456&productId=6543210

CloudEvent

Objet JSON dans la propriété data

{ "customerId": "0123456", "productId": "6543210" }

L'exemple suivant montre une fonction qui reçoit et traite les données d'achat customerId et productId énumérées dans le tableau précédent :

Exemple de fonction Quarkus

public class Functions {
    @Funq
    public void processPurchase(Purchase purchase) {
        // process the purchase
    }
}

La classe JavaBean Purchase correspondante qui contient les données d'achat se présente comme suit :

Exemple de classe

public class Purchase {
    private long customerId;
    private long productId;
    // getters and setters
}

6.4.3.1. Exemples d'invocation

L'exemple de code suivant définit trois fonctions appelées withBeans, withCloudEvent et withBinary;

Exemple :

import io.quarkus.funqy.Funq;
import io.quarkus.funqy.knative.events.CloudEvent;

public class Input {
    private String message;

    // getters and setters
}

public class Output {
    private String message;

    // getters and setters
}

public class Functions {
    @Funq
    public Output withBeans(Input in) {
        // function body
    }

    @Funq
    public CloudEvent<Output> withCloudEvent(CloudEvent<Input> in) {
        // function body
    }

    @Funq
    public void withBinary(byte[] in) {
        // function body
    }
}

La fonction withBeans de la classe Functions peut être invoquée par :

  • Une requête HTTP POST avec un corps JSON :

    $ curl "http://localhost:8080/withBeans" -X POST \
        -H "Content-Type: application/json" \
        -d '{"message": "Hello there."}'
  • Une requête HTTP GET avec des paramètres de requête :

    $ curl "http://localhost:8080/withBeans?message=Hello%20there." -X GET
  • Un objet CloudEvent en codage binaire :

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/json" \
      -H "Ce-SpecVersion: 1.0" \
      -H "Ce-Type: withBeans" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      -d '{"message": "Hello there."}'
  • Un objet CloudEvent dans un encodage structuré :

    $ curl http://localhost:8080/ \
        -H "Content-Type: application/cloudevents+json" \
        -d '{ "data": {"message":"Hello there."},
              "datacontenttype": "application/json",
              "id": "42",
              "source": "curl",
              "type": "withBeans",
              "specversion": "1.0"}'

La fonction withCloudEvent de la classe Functions peut être invoquée en utilisant un objet CloudEvent, de la même manière que la fonction withBeans. Cependant, contrairement à withBeans, withCloudEvent ne peut pas être invoquée avec une simple requête HTTP.

La fonction withBinary de la classe Functions peut être invoquée par :

  • Un objet CloudEvent en codage binaire :

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/octet-stream" \
      -H "Ce-SpecVersion: 1.0"\
      -H "Ce-Type: withBinary" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      --data-binary '@img.jpg'
  • Un objet CloudEvent dans un encodage structuré :

    $ curl http://localhost:8080/ \
      -H "Content-Type: application/cloudevents+json" \
      -d "{ \"data_base64\": \"$(base64 --wrap=0 img.jpg)\",
            \"datacontenttype\": \"application/octet-stream\",
            \"id\": \"42\",
            \"source\": \"curl\",
            \"type\": \"withBinary\",
            \"specversion\": \"1.0\"}"

6.4.4. Attributs du CloudEvent

Si vous devez lire ou écrire les attributs d'un CloudEvent, tel que type ou subject, vous pouvez utiliser l'interface générique CloudEvent<T> et le constructeur CloudEventBuilder. Le paramètre de type <T> doit être l'un des types autorisés.

Dans l'exemple suivant, CloudEventBuilder est utilisé pour renvoyer le succès ou l'échec du traitement de l'achat :

public class Functions {

    private boolean _processPurchase(Purchase purchase) {
        // do stuff
    }

    public CloudEvent<Void> processPurchase(CloudEvent<Purchase> purchaseEvent) {
        System.out.println("subject is: " + purchaseEvent.subject());

        if (!_processPurchase(purchaseEvent.data())) {
            return CloudEventBuilder.create()
                    .type("purchase.error")
                    .build();
        }
        return CloudEventBuilder.create()
                .type("purchase.success")
                .build();
    }
}

6.4.5. Valeurs de retour des fonctions Quarkus

Les fonctions peuvent renvoyer une instance de n'importe quel type de la liste des types autorisés. Elles peuvent également renvoyer le type Uni<T>, où le paramètre de type <T> peut être de n'importe quel type de la liste des types autorisés.

Le type Uni<T> est utile si une fonction fait appel à des API asynchrones, car l'objet renvoyé est sérialisé dans le même format que l'objet reçu. En effet, l'objet retourné est sérialisé dans le même format que l'objet reçu :

  • Si une fonction reçoit une requête HTTP, l'objet renvoyé est envoyé dans le corps de la réponse HTTP.
  • Si une fonction reçoit un objet CloudEvent en codage binaire, l'objet renvoyé est envoyé dans la propriété data d'un objet CloudEvent codé en binaire.

L'exemple suivant montre une fonction qui récupère une liste d'achats :

Example command

public class Functions {
    @Funq
    public List<Purchase> getPurchasesByName(String name) {
      // logic to retrieve purchases
    }
}

  • L'invocation de cette fonction par le biais d'une requête HTTP produit une réponse HTTP qui contient une liste d'achats dans le corps de la réponse.
  • L'invocation de cette fonction par le biais d'un objet CloudEvent entrant produit une réponse CloudEvent avec une liste d'achats dans la propriété data.

6.4.5.1. Types autorisés

L'entrée et la sortie d'une fonction peuvent être de l'un des types void, String ou byte[]. En outre, il peut s'agir de types primitifs et de leurs enveloppes, par exemple int et Integer. Il peut également s'agir des objets complexes suivants : Javabeans, maps, lists, arrays et le type spécial CloudEvents<T>.

Les cartes, les listes, les tableaux, le paramètre de type <T> du type CloudEvents<T> et les attributs des Javabeans ne peuvent être que des types énumérés ici.

Exemple :

public class Functions {
    public List<Integer> getIds();
    public Purchase[] getPurchasesByName(String name);
    public String getNameById(int id);
    public Map<String,Integer> getNameIdMapping();
    public void processImage(byte[] img);
}

6.4.6. Test des fonctions de Quarkus

Les fonctions Quarkus peuvent être testées localement sur votre ordinateur. Dans le projet par défaut qui est créé lorsque vous créez une fonction à l'aide de kn func create, il y a le répertoire src/test/, qui contient les tests Maven de base. Ces tests peuvent être étendus si nécessaire.

Conditions préalables

  • Vous avez créé une fonction Quarkus.
  • Vous avez installé le CLI Knative (kn).

Procédure

  1. Accédez au dossier de projet de votre fonction.
  2. Exécuter les tests Maven :

    $ ./mvnw test

6.4.7. Prochaines étapes

Red Hat logoGithubRedditYoutubeTwitter

Apprendre

Essayez, achetez et vendez

Communautés

À propos de la documentation Red Hat

Nous aidons les utilisateurs de Red Hat à innover et à atteindre leurs objectifs grâce à nos produits et services avec un contenu auquel ils peuvent faire confiance.

Rendre l’open source plus inclusif

Red Hat s'engage à remplacer le langage problématique dans notre code, notre documentation et nos propriétés Web. Pour plus de détails, consultez leBlog Red Hat.

À propos de Red Hat

Nous proposons des solutions renforcées qui facilitent le travail des entreprises sur plusieurs plates-formes et environnements, du centre de données central à la périphérie du réseau.

© 2024 Red Hat, Inc.