Note :

Créer une application Java basée sur Oracle GraalVM à l'aide de Spring Boot sur OKE pour stocker les messages SOAP dans ATP et les envoyer à la file d'attente OCI

Présentation

Beaucoup de nos clients s'appuient sur la messagerie SOAP (Simple Object Access Protocol) traditionnelle pour permettre la communication entre leurs applications. Ils doivent souvent stocker des données transactionnelles, assurer le découplage des services, obtenir l'équilibrage de la charge des demandes entrantes et permettre la communication asynchrone de ces messages.

Dans ce tutoriel, nous allons voir comment créer une application Java basée sur Oracle GraalVM à l'aide de Spring Boot déployée sur l'infrastructure Oracle Cloud Infrastructure Kubernetes Engine (OKE) qui sera utilisée comme intégrateur transactionnel avec les différents services Oracle Cloud Infrastructure (OCI) tels qu'Oracle Autonomous Transaction Processing (ATP) et la file d'attente OCI. Cette configuration permet aux systèmes d'interagir sans connexions directes, ce qui facilite la communication entre les applications avec des vitesses de traitement différentes. De plus, une fois l'information stockée dans la base de données, elle peut être consultée ou analysée.

Nous utiliserons les technologies suivantes :

Services Oracle Cloud Infrastructure (OCI) : OCI est une plate-forme en nuage sécurisée et à haute performance offrant plus de 150 services en nuage. Il est conçu pour l'évolutivité, la sécurité et les performances.

Technologie Oracle :

Autres technologies :

Architecture de haut niveau d'OCI :

Architecture OCI

Architecture de cas d'utilisation

Note :

Objectifs

Préalables

Tâche 1 : Provisionner et configurer la grappe OKE

Dans cette tâche, nous provisionnerons la plate-forme Kubernetes, où l'application prendra en charge tous les messages de transactionnalité élevée SOAP à stocker dans ATP et enverra chacun à la file d'attente OCI en temps réel.

  1. Connectez-vous à la console OCI, naviguez jusqu'à Services de développement, Grappes Kubernetes (OKE) et sélectionnez Compartiment de vos préférences.

    Il y a deux façons de créer une grappe OKE :

    • Création rapide.
    • Création personnalisée.
  2. Sélectionnez Création rapide car cette méthode est plus facile, plus rapide et déploie automatiquement tous les éléments requis par OKE pour son fonctionnement, par exemple :

    • Réseau en nuage virtuel (VCN).
    • Passerelle Internet.
    • Passerelle de traduction d'adresses de réseau (NAT).
    • Passerelle de service.
    • Grappe Kubernetes.
    • Noeud(s) de travail et groupe de noeuds Kubernetes.

    Note : Pour les environnements d'entreprise, où les clients disposent déjà de services, de réseau, d'infrastructure, il est important de personnaliser le déploiement OKE afin qu'il soit conforme, aligné sur l'architecture du client, les ressources et conforme aux meilleures pratiques.

    Création rapide

  3. Cliquez sur Créer une grappe et entrez les informations suivantes.

    • Nom : Entrez le nom de la grappe OKE.
    • Compartiment : Sélectionnez le compartiment créé pour ce projet.
    • Version de Kubernetes : Sélectionnez la dernière version de Kubernetes disponible.
    • Point d'extrémité d'API Kubernetes : Dans ce tutoriel, sélectionnez Point d'extrémité public, mais vous pouvez également sélectionner Point d'extrémité privé.
    • Type de noeud : Sélectionnez des noeuds gérés.
    • Noeuds de travail Kubernetes : Sélectionnez Travailleurs privés.
    • Forme et image : Sélectionnez VM.Standard.E5. Flex, personnalisez le nombre d'OCPU (2) et la mémoire (16 Go) et conservez l'image Oracle Linux 8 par défaut.
    • Nombre de noeuds : Entrez 2 noeuds de travail à déployer avec le groupe de noeuds OKE.

    Créer une grappe OKE

    Vérifiez que la grappe OKE fonctionne.

    OKE en cours d'exécution

Tâche 2 : Provisionnement, configuration et accès au service de registre de conteneurs version classique pour OCI

Nous devons gérer les images de projet dans un référentiel. Pour ce faire, nous provisionnerons le service OCI Container Registry version classique. Une fois les images stockées dans le service de registre de conteneurs version classique d'OCI, nous pourrons les déployer dans OKE.

  1. Allez à la console OCI, naviguez jusqu'à Services de développement, Conteneurs et artefacts, Registre de conteneurs et cliquez sur Créer un référentiel.

  2. Entrez les informations suivantes et cliquez sur Créer.

    • Créer dans le compartiment : Sélectionnez le compartiment créé pour ce projet.
    • Accès : Sélectionnez Public.
    • Nom du référentiel : Entrez springboot/tutorialapp.

    Créer un référentiel

  3. Une fois le référentiel créé, à partir de l'hôte de votre administrateur Oracle, accédez-y à l'aide de la commande suivante.

    docker login -u 'tenancy_namespace/domain/username' regionID.ocir.io
    
    Password: xxxxxx
    

    Authentification du registre Oracle

    OK

Tâche 3 : Provisionner et configurer une base de données sans serveur Oracle Autonomous Transaction Processing (ATP)

Dans la base de données ATP, nous stockons les données de chaque message SOAP reçu par transaction, environ chacune sera de l'ordre des millisecondes, en tenant compte des insertions parallèles et séquentielles.

  1. Allez à la console OCI, naviguez jusqu'à Oracle Database et cliquez sur Autonomous Transaction Processing.

  2. Cliquez sur Créer une base de données Autonomous Database et entrez les informations suivantes.

    • Sélectionner le compartiment : Sélectionnez le compartiment créé pour ce projet.
    • Nom d'affichage : Entrez le nom d'affichage.
    • Afficher le nom de la base de données : Entrez le nom de la base de données.
    • Sélectionner un type de charge de travail : Sélectionnez Traitement des transactions.
    • Sélectionner un type de déploiement : Sélectionnez Sans serveur.
    • Configurez la base de données :
      • Développeur : Désélectionnez-la.
      • Sélectionner une version de base de données : Sélectionnez 23ai.
      • Nombre d'ECPU : Entrez 2.
      • Ajustement automatique du calcul : Sélectionnez-le.
      • Stockage : Entrez 1024 Go.
    • Période de conservation automatique des sauvegardes en jours : Laissez l'option par défaut 60 jours.
    • Créez les données d'identification d'administrateur :
      • Nom d'utilisateur : ADMIN par défaut et ne peut pas être modifié.
      • Mot de passe : Entrez votre mot de passe privilégié.
      • Confirmer le mot de passe : Entrez de nouveau le mot de passe.
    • Sélectionner l'accès au réseau : Sélectionnez Accès au point d'extrémité privé uniquement, puis choisissez le VCN et le sous-réseau créés pour ce projet. Ce paramètre restreint les connexions au réseau privé (VCN) spécifié uniquement. Cependant, vous pouvez choisir d'autres options, cela dépend des besoins de l'entreprise.

    Créer une base de données Oracle ATP

    Créer une base de données Oracle ATP

    Créer une base de données Oracle ATP

    Vérifiez que la base de données ATP est en cours d'exécution.

    Exécution DAV

Tâche 4 : Connecter et créer des tables de projet dans Oracle Autonomous Transaction Processing (ATP)

Maintenant, nous devons configurer, connecter et créer les tables de projet dans la base de données ATP générée à la tâche 3.

  1. Allez à la console OCI, naviguez jusqu'à Oracle Database, Autonomous Transaction Processing et cliquez sur Connexion à la base de données. Sélectionnez Authentification TLS, TLS et cliquez sur Télécharger le portefeuille.

    Connexion à la base de données

  2. Décompressez le fichier .zip du portefeuille et dans tnsnames.ora, vous pouvez obtenir l'URL de la source de données pour obtenir la connexion à cette base de données. Enregistrez cette URL de source de données.

    Par exemple :

    tutorialoracleatp_medium = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=xxxxxxxx.adb.sa-saopaulo-1.oraclecloud.com))(connect_data=(service_name=xxxxxxxxxxxxxxx_tutorialoracleatp_medium.adb.oraclecloud.com))(security=(ssl_server_dn_match=no)))
    
  3. L'accès à la base de données est désormais nécessaire. Lorsque l'ATP a été provisionné, l'accès à Oracle REST Data Services (ORDS) a été activé. Pour plus d'informations, voir Oracle REST Data Services.

    Allez à la page Détails de la base de données Autonomous Database, cliquez sur Actions de base de données. Notez qu'il n'est accessible qu'à partir d'une instance de calcul s'exécutant dans le même réseau en nuage virtuel (VCN).

    Database Actions

  4. Collez l'URL dans le navigateur et accédez à ORDS à l'aide de l'utilisateur et du mot de passe entrés précédemment dans la base de données ATP et accédez au module Oracle SQL Developer Web.

    ORDS

  5. Utilisez les interrogations suivantes pour créer les tables USERS, CARS et HOUSES associées aux messages SOAP que nous recevrons.

    CREATE TABLE USERS (
    username varchar(50) NOT NULL,
    userlastname varchar(50) NOT NULL,
    id int NOT NULL,
    email varchar(50) NOT NULL,
    dateuser varchar(50) NOT NULL,
    attributeuser varchar(50) NOT NULL  
    );
    
    CREATE TABLE CARS (
    userid int NOT NULL,
    brand varchar(50) NOT NULL,
    color varchar(50) NOT NULL,
    plate varchar(50) NOT NULL  
    );
    
    CREATE TABLE HOUSES (
    userid int NOT NULL,
    floors int NOT NULL,
    locationhouse varchar(50) NOT NULL,
    rooms int NOT NULL,
    bathrooms int NOT NULL
    );
    

    Tables créées dans la base de données

Tâche 5 : Provisionner et configurer la file d'attente OCI

Dans la file d'attente OCI, nous stockerons des messages hautement transactionnels au moyen de l'API HTTP RESTful pendant une période spécifique. Les consommateurs peuvent ensuite lire et supprimer les messages immédiatement ou à leur convenance, ce qui assure le découplage et empêche la perte de données.

  1. Allez à la console OCI, naviguez jusqu'à Services de développement, Intégration d'applications et cliquez sur Files d'attente.

  2. Cliquez sur Créer une file d'attente, entrez les informations suivantes et cliquez sur Créer une file d'attente.

    • Nom : Entrez le nom approprié pour votre file d'attente.
    • Compartiment : Sélectionnez votre compartiment de travail.
    • Paramètres de file d'attente : Dans ce tutoriel, nous sélectionnerons Configuration par défaut, mais si vous le souhaitez, vous pouvez personnaliser plusieurs options en fonction des besoins de l'entreprise tels que : Temporisation de visibilité, Période de conservation maximale, Consommation maximale du canal et File d'attente des lettres mortes.
    • Configurer les paramètres de chiffrement : Sélectionnez Clé gérée par Oracle, mais la clé gérée par le client est également une option.

    Créer une file d'attente

    Vérifiez que la file d'attente OCI est en cours d'exécution.

    File d'attente OCI en cours d'exécution

Tâche 6 : Créer une application Java basée sur Oracle GraalVM avec Spring Boot et la déployer dans OKE

Maintenant, nous allons développer et déployer une application Java basée sur Oracle GraalVM sur Spring Boot qui effectuera les tâches suivantes :

Note : Avant de commencer, il est important de créer un hôte d'administration et un environnement de développement, comme indiqué dans les sections Préalables - Hôte d'administration et Préalables - Environnement de développement.

Une fois que votre hôte d'administration et votre environnement de développement sont configurés et prêts, vous pouvez commencer à développer votre projet Spring Boot.

  1. Allez à Spring initializr et créez le premier projet qui nous donnera la structure des dossiers et les fichiers de base d'un projet Spring Boot, pour le modifier ultérieurement en fonction de nos besoins. Entrez les informations suivantes et cliquez sur Générer. Le projet Spring Boot sera automatiquement téléchargé, enregistré et décompressé dans votre hôte de développement.

    • Projet : Sélectionnez Maven.
    • Langue : Sélectionnez Java.
    • Démarrage du ressort : Sélectionnez 3.3.6.
    • Métadonnées de projet :
      • Groupe : Entrez com.tutorial_springboot.
      • Artefact : Entrez un tutoriel.
      • Nom : Entrez le tutoriel.
      • Description : Entrez Spring Boot Application (lire SOAP, transformer en JSON, insérer ATP et placer dans la file d'attente OCI).
    • Emballage : Sélectionnez Jar.
    • Java : Sélectionnez 17.
    • Dépendances : Sélectionnez Pilote Oracle, Services Web Spring et Web Spring.

    Note : Nous pouvons ajouter certaines dépendances dans le projet, puis en ajouter d'autres, directement dans le fichier pom.xml, selon nos besoins.

    Projet Springboot

  2. Maintenant, nous avons le projet de structure de démarrage de ressort.

    Projet de démarrage de Structure Spring

    Consultez le fichier pom.xml, nous allons commencer à travailler dessus.

    Fichier POM initial

    Mettez à jour le fichier pom.xml, en fonction de la portée proposée dans ce tutoriel.

    • Ajoutez la version oci sdk et les dépendances suivantes.

      • oci-java-sdk-common.
      • oci-java-sdk-queue.
      • oci-java-sdk-addons-oke-workload-identity.
      • oci-java-sdk-common-httpclient-jersey3.

      L'application devra s'authentifier auprès d'OCI, se connecter et gérer des services OCI, tels que la file d'attente OCI.

    • Notre fichier pom.xml comporte déjà une dépendance spring-boot-starter-web-services et nous devons ajouter une dépendance wsdl4j. L'objectif principal est d'obtenir les données reçues des messages SOAP et de les placer dans des objets Java, la création de services Web printaniers manipulant les données utiles XML, vise à faciliter le développement de services SOAP d'abord contractuels. Permet également de configurer le port, l'URI et le schéma XML chargé à partir du fichier XSD (XML Schema Definition).

    • Ajouter une dépendance JSON. Cette bibliothèque sera utilisée pour générer le format JSON avec les données extraites du message SOAP.

    • Ajoutez le plugiciel spring-boot-maven-plugin dans la section Créer. Ce plugin nous permettra de générer le fichier de projet jar exécutable Spring Boot.

    • Ajoutez le plugiciel jaxb2-maven-plugin dans la section Créer. Ce plugiciel utilisera l'API Java pour la liaison XML (JAXB), pour générer des classes Java à partir de schémas XML et de cette façon, nous pouvons transmettre les données du message SOAP aux objets de classe Java que nous avons créés.

      Dans cette section plugin, il est important de mettre la configuration qui indiquera le chemin, où le fichier XSD est inclus dans notre projet Spring Boot.

      <configuration>
         <sources>
         <source>${project.basedir}/src/main/resources/messages.xsd<source>
         </sources>
      </configuration>
      
    • Ajoutez la dépendance jasypt-spring-boot-starter dans la section Dépendances et le plugiciel jasypt-maven-plugin dans la section Créer, ce qui nous permettra de chiffrer les paramètres sensibles dans le fichier application.properties, assurant ainsi une utilisation sécurisée dans notre application.

    Vérifiez les dépendances suivantes ajoutées dans le fichier pom.xml.

    Fichier POM modifié

    Fichier POM modifié

  3. Téléchargez les bibliothèques et exécutez les commandes suivantes.

    1. Dans votre environnement de développement, exécutez la commande suivante pour accéder à votre projet.

      cd tutorial
      

      Dossier de projet de démarrage Spring

    2. Nettoyez le projet et supprimez tous les fichiers générés par la compilation précédente.

      mvn clean
      

      Nettoyage de Maven

    3. Épurer (supprimer et éventuellement résoudre de nouveau) les artefacts du référentiel maven local.

      mvn dependency:purge-local-repository
      

    Dépendances d'épuration Maven

  4. Déjà nous avons les dépendances et le fichier pom.xml configurés dans notre projet, nous allons procéder à la vérification du fichier XML SOAP, car il représente la demande du côté du client, et le fichier XSD, qui interprète la demande du côté de notre projet Spring Boot.

    1. Ce fichier XML SOAP contient deux messages, avec des informations personnelles et d'autres types d'attributs de deux clients différents que nous enverrons par demande, comme indiqué dans l'image suivante.

      Fichier de savon

    2. Maintenant, du côté de notre projet Spring Boot, un schéma XML est nécessaire pour définir un domaine de service Web que le service Web Spring exporte automatiquement en tant que WSDL, l'image suivante montre le fichier messages.xsd défini pour ce tutoriel.

      messages.xsd:

      Fichier XSD

    3. Enregistrez le fichier messages.xsd dans le dossier de ressources de votre projet Spring Boot.

      Fichier XSD dans le dossier

  5. Créez et installez des fichiers de projet dans un fichier JAR. Exécutez la commande suivante et assurez-vous que vous êtes dans votre dossier de projet Spring Boot.

    mvn install
    

    Note : Une fois la commande d'installation maven exécutée, le dossier cible est automatiquement généré et, de la même manière, les classes Java en fonction du fichier XSD créé précédemment et du fichier .jar exécutable du projet.

    Dossier cible

  6. Maintenant, nous pouvons ajouter les classes Java requises à notre projet Spring Boot.

    WebServiceConfig.java Class: Cette classe Java a été développée pour créer un service Web SOAP :

    • Configure le servlet pour traiter les demandes SOAP.
    • Génère une définition WSDL basée sur un schéma XML.
    • Définit le point d'extrémité d'accès du service Web SOAP.
    • Utilise le fichier de schéma messages.xsd de la variable classpath.
    //Imports
    import org.springframework.boot.web.servlet.ServletRegistrationBean; //import the ServletRegistrationBean class
    import org.springframework.context.ApplicationContext; //import the ApplicationContext class
    import org.springframework.context.annotation.Bean; //import the Bean class
    import org.springframework.context.annotation.Configuration; //import the Configuration class
    import org.springframework.core.io.ClassPathResource; //import the ClassPathResource class
    import org.springframework.ws.config.annotation.EnableWs; //import the EnableWs class
    import org.springframework.ws.config.annotation.WsConfigurerAdapter; //import the WsConfigurerAdapter class
    import org.springframework.ws.transport.http.MessageDispatcherServlet; //import the MessageDispatcherServlet class
    import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; //import the DefaultWsdl11Definition class
    import org.springframework.xml.xsd.SimpleXsdSchema; //import the SimpleXsdSchema class
    import org.springframework.xml.xsd.XsdSchema; //import the XsdSchema class
    
    //Configuration class for the Web Service configuration
    @EnableWs //Enable the Web Service
    @Configuration //Define the class as a Configuration class 
    
    public class WebServiceConfig extends WsConfigurerAdapter {
    
       //Create a ServletRegistrationBean object to register the MessageDispatcherServlet object with the application context
       @Bean
       public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
          MessageDispatcherServlet servlet = new MessageDispatcherServlet(); //Create a MessageDispatcherServlet object
          servlet.setApplicationContext(applicationContext); //Set the application context for the MessageDispatcherServlet object
          servlet.setTransformWsdlLocations(true); //Set the transformWsdlLocations property to true
          return new ServletRegistrationBean<>(servlet, "/ws/*"); //Return a new ServletRegistrationBean object with the MessageDispatcherServlet object and the URL pattern
       }
    
       //Create a DefaultWsdl11Definition object to define the WSDL
       @Bean(name = "messages")
       public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema messagesSchema) {
          DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); //Create a DefaultWsdl11Definition object
          wsdl11Definition.setPortTypeName("MessagesPort"); //Set the port type name
          wsdl11Definition.setLocationUri("/ws"); //Set the location URI
          wsdl11Definition.setTargetNamespace("http://tutorial_example.com/ns0"); //Set the target namespace
          wsdl11Definition.setSchema(messagesSchema); //Set the schema
          return wsdl11Definition; //Return the DefaultWsdl11Definition object
       }
    
       //Create a XsdSchema object to define the schema
       @Bean
       public XsdSchema messagesSchema() {
          return new SimpleXsdSchema(new ClassPathResource("messages.xsd")); //Return a new SimpleXsdSchema object with the messages.xsd file
       }
    }
    

    Note : Si vous voulez tester le service Web, vous pouvez exécuter le projet Spring Boot dans le même bureau d'environnement de développement local et envoyer une demande HTTP à l'aide de curl, comme suit :

    mvn spring-boot:run
    

    Exécuter le projet de démarrage Spring

    Exécuter le projet de démarrage Spring

    Une fois le projet en cours d'exécution et le service Web en cours d'exécution, exécutez une demande HTTP SOAP locale à l'aide de curl, comme suit :

    curl --location 'http://localhost:8080/ws/'
    

    Et vous obtiendrez une réponse du service Web exposé dans notre projet Spring Boot.

    Service Web SOAP

  7. Créez un dossier nommé model et dans ce dossier, nous ajouterons les classes Java suivantes.

    Dossier de modèles

    Note : Ces classes Java Car, House et User extrairont les informations basées sur les données de chaque message SOAP extrait de la demande SOAP HTTP.

    • Car.java class: Cette classe Java représente un objet Car dont les attributs sont liés à chaque utilisateur.

      ```
      //Imports
      import org.springframework.stereotype.Component; // For component scanning
      import org.springframework.context.annotation.Scope; // For defining bean scope
      
      @Component // Marks a class as a Spring-managed component
      @Scope("prototype") //A new instance is created every time the bean is requested
      
      public class Car {
      
         //Attributes
      
         private String brand; 
         private String color; 
         private String plate; 
      
         //"getter" and "setter" methods to get and set the information in each object
      
         public String getBrand(){
         return brand;
         }
      
         public void setBrand(String brand){
         this.brand = brand;
         }
      
         public String getColor(){
         return color;
         }
      
         public void setColor(String color){
         this.color = color;
         }
      
         public String getPlate(){
         return plate;
         }
      
         public void setPlate(String plate){
         this.plate = plate;
         }
      
      }
      ```
      
      • House.java class: Cette classe Java représente un objet Maison dont les attributs sont liés à chaque utilisateur.

        //Imports
        import org.springframework.stereotype.Component; // For component scanning
        import org.springframework.context.annotation.Scope; // For defining bean scope
        
        @Component // Marks a class as a Spring-managed component
        @Scope("prototype") //A new instance is created every time the bean is requested
        
        public class House {
        
           //Attributes
        
           private int floors;
           private String location;
           private int rooms;
           private int bathrooms;
        
        
           //"getter" and "setter" methods to get and set the information in each object
        
           public int getFloors(){
              return floors;
           }
        
           public void setFloors(int floors){
              this.floors = floors;
           }
        
           public String getLocation(){
              return location;
           }
        
           public void setLocation(String location){
              this.location = location;
           }
        
           public int getRooms(){
              return rooms;
           }
        
           public void setRooms(int rooms){
              this.rooms = rooms;
           }
        
           public int getBathRooms(){
              return bathrooms;
           }
        
           public void setBathRooms(int bathrooms){
              this.bathrooms = bathrooms;
           }
        
        }
        
      • User.java class: Cette classe Java représente un objet Utilisateur avec ses attributs, contenant des objets Car et Maison.

        //Imports
        import org.springframework.stereotype.Component; // For component scanning
        import org.springframework.context.annotation.Scope; // For defining bean scope
        
        @Component // Marks a class as a Spring-managed component
        @Scope("prototype") //A new instance is created every time the bean is requested
        
        
        public class User {
        
           //Attributes
        
           private String username; 
           private String userlastname;
           private int id;
           private String email;
           private String date;
           private String attribute;
           private Car car;
           private House house;
        
        
           //"getter" and "setter" methods to get and set the information in each object
        
           public String getUserName(){
           return username;
           }
        
           public void setUserName(String username){
           this.username = username;
           }
        
           public String getUserLastName(){
           return userlastname;
           }
        
           public void setUserLastName(String userlastname){
           this.userlastname = userlastname;
           }    
        
           public int getID(){
           return id;
           }
        
           public void setID(int id){
           this.id = id;
           }        
        
           public String getEmail(){
           return email;
           }
        
           public void setEmail(String email){
           this.email = email;
           }
        
           public String getDate(){
           return date;
           }
        
           public void setDate(String date){
           this.date = date;
           }
        
           public String getAttribute(){
           return attribute;
           }
        
           public void setAttribute(String attribute){
           this.attribute = attribute;
           }
        
           public Car getCar(){
           return car;
           }
        
           public void setCar(Car car){
           this.car = car;
           }
        
           public House getHouse(){
           return house;
           }
        
           public void setHouse(House house){
           this.house = house;
           }
        }
        
  8. Nous allons maintenant configurer les paramètres nécessaires dans notre projet Spring Boot pour stocker les données obtenues dans la base de données ATP OCI. Dans le dossier resources, vous devez trouver le fichier application.properties utilisé pour ajouter les paramètres requis par l'application. Il est généré automatiquement et chargé par Spring Boot au démarrage de l'application.

    Note : Il est vraiment important de gérer les méthodes de chiffrement et de sécurité qui garantissent que les informations sensibles, telles que les mots de passe ou les données pertinentes, ne peuvent pas être extraites ou consultées par les pirates. Dans ce tutoriel, nous utilisons la bibliothèque jasypt configurée dans le fichier pom.xml. Pour plus d'informations, voir Comment chiffrer les mots de passe dans un projet Spring Boot à l'aide de Jasypt. De plus, dans nos classes Java sur Spring Boot, il est documenté où ajouter les annotations et le code source liés à cette bibliothèque pour déchiffrer les paramètres application.properties.

    Ajoutez les paramètres appropriés requis par la base de données ATP dans le fichier application.properties, comme illustré dans l'image suivante.

    Fichier de propriétés d'application

    Créez la classe Java Spring Boot pour stocker chaque message dans la base de données. Il se trouve dans le dossier database, comme illustré dans l'image suivante.

    Dossier Base de données

    • SoapObjectRepository.java: Cette classe Java Spring Boot permet d'insérer dans un formulaire transactionnel en temps réel, chaque message dans ATP, à l'aide du pilote JDBC.

      //Java Classes USER, CAR, HOUSE Imports
      import com.oracle_springboot_tutorial.tutorial.model.*;
      
      //Spring Boot Imports
      import org.springframework.stereotype.Repository;
      import org.springframework.jdbc.core.JdbcTemplate;
      import org.springframework.beans.factory.annotation.Autowired;
      
      //Repository Class to save SOAP Messages in the Database
      @Repository
      public class SoapObjectRepository {
         private JdbcTemplate template;
         private User user;
      
         //Getters and Setters for JdbcTemplate template object
         public JdbcTemplate getTemplate(){
            return template;
         }
      
         //Autowired annotation to inject JdbcTemplate object into the template object
         @Autowired
         public void setTemplate(JdbcTemplate template){
            this.template = template;
         }
      
         //Method to save User SOAP Message in the Database
         public void saveUserSOAPMessage(User user){
            this.user = user;
            String sql = "INSERT INTO USERS (username, userlastname, id, email, dateuser, attributeuser) VALUES(?, ?, ?, ?, ?, ?)";
            template.update(sql, user.getUserName(), user.getUserLastName(), user.getID(), user.getEmail(), user.getDate(), user.getAttribute());
         }
      
         //Method to save Car SOAP Message in the Database
         public void saveCarSOAPMessage(Car car){
            String sql = "INSERT INTO CARS (userid, brand, color, plate) VALUES(?, ?, ?, ?)";
            template.update(sql, user.getID(), car.getBrand(), car.getColor(), car.getPlate());
         }
      
         //Method to save House SOAP Message in the Database
         public void saveHouseSOAPMessage(House house){
            String sql = "INSERT INTO HOUSES (userid, floors, locationhouse, rooms, bathrooms) VALUES(?, ?, ?, ?, ?)";
            template.update(sql, user.getID(), house.getFloors(), house.getLocation(), house.getRooms(), house.getBathRooms());
         }
      
      
      }
      

      Maintenant, ajoutez le code logiciel JSON, en créant d'abord le dossier json_message et sa classe Java Spring Boot, comme illustré dans l'image suivante.

      Dossier Json

    • JsonBuilder.java: Cette classe Java Spring Boot convertit du format XML SOAP au format JSON.

      //Imports to be used for JSON
      import org.json.JSONArray;
      import org.json.JSONObject;
      
      //Imports to be used for the User class
      import com.oracle_springboot_tutorial.tutorial.model.*;
      
      
      //Imports to be used for the ArrayList class
      import java.util.ArrayList;
      
      
      public class JsonBuilder {
      
         //The buildJsonMessage method creates a JSON object from the ArrayList of User objects
         public JSONObject buildJsonMessage(ArrayList<User> usersMessageArray) {
      
            JSONObject rootJson = new JSONObject(); //Create a new JSON object called rootJson
            JSONObject messagesJson = new JSONObject(); //Create a new JSON object called messagesJson
            JSONArray messageArray = new JSONArray(); //Create a new JSON array called messageArray
      
      
            //Iterate through the ArrayList of User objects and create a JSON object for each User object in the ArrayList
            for (User user : usersMessageArray) {
                  JSONObject messageJson = new JSONObject();
                  messageJson.put("username", user.getUserName()); //Add the username of the user to the messageJson object
                  messageJson.put("userlastname", user.getUserLastName()); //Add the userlastname of the user to the messageJson object
                  messageJson.put("id", user.getID()); //Add the id of the user to the messageJson object
                  messageJson.put("email", user.getEmail()); //Add the email of the user to the messageJson object
                  messageJson.put("date", user.getDate()); //Add the date of the user to the messageJson object
                  messageJson.put("attribute", user.getAttribute()); //Add the attribute of the user to the messageJson object
      
      
                  //
                  JSONObject bodyJson = new JSONObject(); //Create a new JSON object called bodyJson
                  JSONObject envelopeJson = new JSONObject(); //Create a new JSON object called envelopeJson
      
                  //Switch statement to check the attribute of the User object
                  switch (user.getAttribute()) {
                     case "CAR":
                              Car car = user.getCar();
                              envelopeJson.put("brand", car.getBrand()); //Add the brand of the car to the envelopeJson object
                              envelopeJson.put("color", car.getColor()); //Add the color of the car to the envelopeJson object
                              envelopeJson.put("plate", car.getPlate()); //Add the plate of the car to the envelopeJson object                       
                        break;
                     case "HOUSE":
                              House house = user.getHouse();
                              envelopeJson.put("floors", house.getFloors()); //Add the floors of the house to the envelopeJson object
                              envelopeJson.put("location", house.getLocation()); //Add the location of the house to the envelopeJson object
                              envelopeJson.put("rooms", house.getRooms()); //Add the rooms of the house to the envelopeJson object
                              envelopeJson.put("bathrooms", house.getBathRooms()); //Add the bathrooms of the house to the envelopeJson object                     
                        break;
                     default:
                        System.out.println("Unknown subject: " + user.getAttribute());
                  }
      
      
                  bodyJson.put("envelope", envelopeJson); //Add the envelopeJson object to the bodyJson object
      
                  messageJson.put("body", bodyJson); //Add the bodyJson object to the messageJson object
      
               messageArray.put(messageJson); //Add the messageJson object to the messageArray array
            }
      
            messagesJson.put("message", messageArray); //Add the messageArray array to the messagesJson object
            rootJson.put("messages", messagesJson); //Add the messagesJson object to the rootJson object
      
            return rootJson;
         }
      }
      
  9. Désormais, nous pouvons envoyer les messages au format JSON à la file d'attente OCI. Créez le dossier oci_queue et sa classe Spring Boot Java, comme illustré dans l'image suivante.

    Dossier de file d'attente

    Note : Dans la classe OCIQueue.java, nous devrons définir l'accès d'OKE à la file d'attente OCI. Pour ce tutoriel, nous utiliserons l'accès aux charges de travail pour accorder l'accès aux ressources OCI, sans avoir à gérer les informations sensibles telles que l'utilisateur, les mots de passe, les OCID associés à votre location. Pour plus d'informations, voir Octroi de l'accès aux ressources OCI pour les charges de travail.

    Avant de commencer à développer la classe OCIQueue.java, nous configurerons l'accès aux charges de travail dans notre location. Tout d'abord, nous devons créer un espace de noms à associer à notre application Java basée sur Oracle GraalVM. Assurez-vous d'être dans l'hôte administrateur.

    kubectl create ns-tutorial
    

    Créez ensuite un compte de service Kubernetes pour l'application.

    kubectl create serviceaccount tutorialserviceaccount --namespace ns-tutorial
    

    Maintenant, définissez une politique OCI IAM pour permettre à la charge de travail d'accéder aux ressources OCI nécessaires. Dans ce tutoriel, file d'attente OCI.

    Allez à la console OCI, naviguez jusqu'à Identité et sécurité, Politiques et cliquez sur Créer une politique. Entrez les informations suivantes et cliquez sur Créer.

    • Nom : Entrez le nom de la politique privilégiée.
    • Description : Entrez Accès de oke à la file d'attente oci.
    • Générateur de politiques :

      Allow any-user to use queues in compartment id ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx where all {request.principal.type = 'workload', request.principal.namespace = 'ns-tutorial', request.principal.service_account = 'tutorialserviceaccount', request.principal.cluster_id = 'ocid1.cluster.oc1.sa-saopaulo-1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
      

    Politique d'accès aux charges de travail

    Une fois que vous avez configuré la politique d'accès à la charge de travail, l'espace de noms et le compte de service, nous pouvons continuer.

    Dans le fichier application.properties, ajoutez les paramètres de file d'attente requis pour la connexion et la gestion de la file d'attente OCI spécifique créée dans la tâche 5.

    Paramètres OCIID

    • OCIQueue.java: Cette classe Java Spring Boot permet d'accéder aux messages et de les placer dans la file d'attente OCI.

      //Imports
      import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider; //Import OkeWorkloadIdentityAuthenticationDetailsProvider to enable access and use OCI Workload Identity
      import com.oracle.bmc.queue.QueueClient; //Import QueueClient to have access and manage of OCI Queue
      import com.oracle.bmc.queue.model.PutMessagesDetails; //Import PutMessagesDetails to send messages to the OCI Queue
      import com.oracle.bmc.queue.model.PutMessagesDetailsEntry; //Import PutMessagesDetailsEntry to send messages to the OCI Queue
      import com.oracle.bmc.queue.requests.PutMessagesRequest; //Import PutMessagesRequest to send messages to the OCI Queue
      
      //Imports for the ArrayList and List
      import java.util.ArrayList;
      import java.util.List;
      
      public class OCIQueue {
         //Set the required parameters to access to OCI and the Queue
      
         //Variables
         private String queueId; 
         private String endPoint;
         private String region;
      
         //Constructor to initialize the OCI Queue object with the required parameters
         public OCIQueue(String queueId, String endPoint, String region){
            this.queueId = queueId;
            this.endPoint = endPoint;
            this.region = region;   
         }
      
      
         //The sendMessages method sends a message to the OCI Queue
         public void sendMessages(String jsonMessage){
            try{    
      
                  //Create an OkeWorkloadIdentityAuthenticationDetailsProvider object to authenticate the OCI Queue
                  OkeWorkloadIdentityAuthenticationDetailsProvider provider = new OkeWorkloadIdentityAuthenticationDetailsProvider.OkeWorkloadIdentityAuthenticationDetailsProviderBuilder().build();
      
                  //Create a QueueClient object to send the message to the OCI Queue
                  QueueClient queueClient = QueueClient.builder().build(provider);
                  queueClient.setRegion(region);
                  queueClient.setEndpoint(endPoint);
      
      
      
                  //Create a PutMessagesDetailsEntry object to send the message
                  PutMessagesDetailsEntry message = PutMessagesDetailsEntry.builder()
                     .content(jsonMessage)
                     .build();
      
                  //Create a List of PutMessagesDetailsEntry objects to send the message
                  List<PutMessagesDetailsEntry> messages = new ArrayList<>();
                  messages.add(message);
      
                  //Create a PutMessagesDetails object to send the message
                  PutMessagesDetails putMessagesDetails = PutMessagesDetails.builder()
                     .messages(messages)
                     .build();
      
      
                  //  Create a PutMessagesRequest object to send the message
                  PutMessagesRequest putMessagesRequest = PutMessagesRequest.builder()
                     .queueId(queueId)
                     .putMessagesDetails(putMessagesDetails)
                     .build();
      
                  // Send the request and get the response
                  queueClient.putMessages(putMessagesRequest);
      
            }catch(Exception e){
                  System.out.println("Exception sending message to OCI Queue: "+e);
            }
         }
      }
      
  10. Une fois que vous avez les classes Java Spring Boot pour la base de données, JSON et la file d'attente OCI, nous pouvons passer à la classe MessagesEndpoint.java.

    Pour cela, nous allons créer un dossier nommé endpoint et sa classe Java Spring Boot.

    Dossier de point d'extrémité

    Note : Dans MessagesEndpoint.java, nous devons importer certaines classes générées automatiquement. Pour ce faire, ajoutez la source suivante dans la section Configuration du fichier pom.xml :

    <configuration>
       <sources>
       <source>${project.build.directory}/generated-sources</source>
       </sources>
    </configuration>
    

    Le fichier pom.xml doit ressembler.

    Chemin des sources générées

    • MessagesEndpoint.java: Le but de cette classe Java Spring Boot est d'extraire la demande HTTP SOAP et de mapper ses valeurs aux objets Java User, Car et House pour chaque message. Il stocke ensuite les données extraites dans une base de données ATP pour chaque transaction XML SOAP, convertit les données du format XML au format JSON et place les messages dans une file d'attente OCI. Ces messages peuvent ensuite être extraits et supprimés de la file d'attente par les consommateurs.

      //Imports
      import com.oracle_springboot_tutorial.tutorial.model.*; //Import all the classes from the model package
      import com.oracle_springboot_tutorial.tutorial.oci_queue.OCIQueue; //Import the OCIQueue class from the oci_queue package
      
      
      import com.tutorial_example.ns0.Messages;//Import the Messages class from the tutorial_example.ns0 package (Auto generated Java Classes from the WSDL)
      import com.tutorial_example.ns0.MessageType; //Import the MessageType class from the tutorial_example.ns0 package (Auto generated Java Classes from the WSDL)
      
      //Import the ArrayList class from the java.util package
      import java.util.ArrayList;
      
      //Spring Boot imports to be used for the SOAP Web Service
      import org.springframework.beans.factory.annotation.Autowired; //Import the @Autowired annotation to inject the SoapObjectRepository object
      import org.springframework.beans.factory.annotation.Value; //Import the @Value annotation to inject the values from the application.properties file
      import org.springframework.stereotype.Component; //Import the @Component annotation to register the class with Spring
      
      //Spring Boot imports 
      import org.springframework.ws.server.endpoint.annotation.Endpoint; //Import the @Endpoint annotation to register the class with Spring WS
      import org.springframework.ws.server.endpoint.annotation.PayloadRoot; //Import the @PayloadRoot annotation to specify the namespace URI and local part of the request payload
      import org.springframework.ws.server.endpoint.annotation.RequestPayload; //Import the @RequestPayload annotation to map the request payload to the method parameter
      import org.springframework.ws.server.endpoint.annotation.ResponsePayload; //Import the @ResponsePayload annotation to map the returned value to the response payload
      
      //Imports to be used storing SOAP information in the database 
      import com.oracle_springboot_tutorial.tutorial.database.SoapObjectRepository; //Import the SoapObjectRepository class from the database package
      
      //Imports to be used for JSON
      import com.oracle_springboot_tutorial.tutorial.json_message.JsonBuilder; //Import the JsonBuilder class from the json_message package 
      import org.json.JSONObject; //Import the JSONObject class from the org.json package
      
      
      //The @Endpoint annotation registers the class with Spring WS.
      //The @Component annotation registers the class with Spring to be used as a Spring Bean.
      @Endpoint
      @Component
      public class MessagesEndpoint {
      
         //Inject not encrypted and decrypted values using jasypt library from the application.properties file
         @Value("${oci.queue.queueId}")
         private String queueId;
         @Value("${oci.queue.endPoint}")
         private String endPoint;
         @Value("${oci.queue.region}")   
         private String region;
         @Value("${spring.datasource.password}")
         private String datasourcePassword;
      
         //The @Autowired loads JDBC template in SoapObjectRepository.
         @Autowired
         private SoapObjectRepository soapObjectRepository = new SoapObjectRepository();
         //Create a new instance of the JsonBuilder class
         JsonBuilder jsonBuilder = new JsonBuilder();
      
      
         //The namespace URI
         private static final String NAMESPACE_URI = "http://tutorial_example.com/ns0";
      
         //The handleMessagesRequest method is annotated with @PayloadRoot, which means that it is invoked when a request with the specified namespace URI and local part is received.
         @PayloadRoot(namespace = NAMESPACE_URI, localPart = "messages")
         //The @ResponsePayload annotation makes Spring WS map the returned value to the response payload.
         @ResponsePayload
         //The handleMessagesRequest method processes the request and sends the message to the OCI Queue.
         public void handleMessagesRequest(@RequestPayload Messages request) {
            OCIQueue ociQueue = new OCIQueue(queueId, endPoint, region);
      
            //Create an ArrayList to store the users
            ArrayList<User> usersMessageArray = new ArrayList<User>();
      
            //Iterate over the messages, extracting the SOAP Messages and storing in the Java Objects (Car, House, User) 
            for (MessageType message : request.getMessage()) {
      
                  User user = new User();
                  user.setUserName(message.getUsername());
                  user.setUserLastName(message.getUserlastname());
                  user.setID(message.getId());
                  user.setEmail(message.getEmail());
                  user.setDate(message.getDate());
                  user.setAttribute(message.getAttribute());
      
                  //Insert User in Oracle ATP
                  soapObjectRepository.saveUserSOAPMessage(user);
      
                  //Process the attributes Car or House depending of the kind of User
                  processMessage(user, message);
                  //Add the user to the ArrayList
                  usersMessageArray.add(user);
            }
      
      
            //Convert to JSON format
            JSONObject jsonObject = jsonBuilder.buildJsonMessage(usersMessageArray);
      
            //Send the JSON message to OCI Queue
            ociQueue.sendMessages(jsonObject.toString());
      
         }
      
         //The processMessage method processes the message based on the user's attribute.
         private void processMessage(User user, MessageType message) {
            String subject = user.getAttribute();
            switch (subject) {
                  case "CAR":
                     handleCAR(user, message);
                     break;
                  case "HOUSE":
                     handleHouse(user, message);
                     break;
                  default:
                     System.out.println("Unknown subject: " + subject);
            }
         }
      
         //The handleCAR method processes the CAR message.
         private void handleCAR(User user, MessageType message) {
            Car car = new Car();
            car.setBrand(message.getBody().getEnvelope().getBrand());
            car.setColor(message.getBody().getEnvelope().getColor());
            car.setPlate(message.getBody().getEnvelope().getPlate());
      
            user.setCar(car);
            //Insert Car in Oracle ATP
            soapObjectRepository.saveCarSOAPMessage(user.getCar());
      
         }
      
         //The handleHouse method processes the HOUSE message.
         private void handleHouse(User user, MessageType message) {
            House house = new House();
            house.setFloors(message.getBody().getEnvelope().getFloors());
            house.setLocation(message.getBody().getEnvelope().getLocation());
            house.setRooms(message.getBody().getEnvelope().getRooms());
            house.setBathRooms(message.getBody().getEnvelope().getBathrooms());
      
            user.setHouse(house);
      
            //Insert Houses in Oracle ATP
            soapObjectRepository.saveHouseSOAPMessage(user.getHouse());
      
         }
      }
      
  11. Maintenant que nous avons terminé la construction complète du projet Spring Boot, nous allons créer Dockerfile dans le dossier du projet.

  1. Exécutez la commande suivante pour créer et pousser l'image du projet dans le référentiel Docker local.

    docker build . -t springbootapp:latest
    

    Créer une image Docker

  2. Exécutez la commande suivante pour vérifier l'image dans le référentiel Docker local.

    docker images
    

    Repo local d'image Docker

  3. Nous pouvons marquer l'image de l'application Spring Boot avec le chemin complet de votre référentiel OCI Container Registry version classique.

    docker tag springbootapp:latest gru.ocir.io/xxxxxxxxxx/springboot/tutorialapp:latest
    
  4. Exécutez la commande suivante pour vérifier dans le référentiel Docker local.

    docker images
    

    Marquer l'application OKE

  5. Exécutez la commande suivante pour pousser l'image vers le service de registre de conteneurs pour OCI version classique.

    docker push gru.ocir.io/xxxxxxxxxx/springboot/tutorialapp:latest
    

    Pousser l'application OKE

  6. Pour vérifier l'application d'image OKE dans OCI Container Registry version classique, allez à Services de développement, Conteneurs et artefacts et cliquez sur Container Registry.

    Image dans OKE Containe Registry

    Une fois l'image trouvée dans le service OCI Container Registry version classique, nous pouvons accéder à notre environnement de développement et déployer cette image dans OKE. Pour ce tutoriel, exécutez la commande suivante pour créer les configurations requises.

    Note : Comme l'espace de noms et le compte de service ont été configurés auparavant, la clé secrète est requise.

    1. Exécutez la commande suivante pour accéder au dossier du projet.

      cd tutorial/
      
    2. Exécutez la commande suivante pour créer une clé secrète pour OKE.

      kubectl create secret -n ns-tutorial generic ocir --from-file=.dockerconfigjson=../.docker/config.json --type=kubernetes.io/dockerconfigjson
      

      Créer une opération sécurisée

  7. Nous avons déjà un environnement OKE prêt. Déployez l'image d'application du service Container Registry version classique d'OCI vers OKE.

    Note : Pour déployer l'image d'application, il est nécessaire d'avoir un fichier manifeste. Dans ce tutoriel, le fichier yaml suivant est le fichier manifeste. Il est utilisé pour déployer l'application et créer le service entrant représenté dans un équilibreur de charge OCI qui écoute à l'aide du port 80.

    • springboot_application.yaml:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: soap-oci-queue-app
      namespace: ns-tutorial 
      labels:
         app: soap-oci-queue-app
      spec:
      replicas: 6
      selector:
         matchLabels:
            app: soap-oci-queue-app
      template:
         metadata:
            labels:
            app: soap-oci-queue-app
         spec:
            serviceAccountName: tutorialserviceaccount
            automountServiceAccountToken: true      
            containers:
            - name: soap-oci-queue-app
            image: gru.ocir.io/xxxxxxxxxxxx/springboot/tutorialapp:latest
            ports:
            - containerPort: 8080
            imagePullSecrets:
            - name: ocir-docker-config
      ---
      
      apiVersion: v1
      kind: Service
      metadata:
      name: svc-dev-app 
      namespace: ns-tutorial 
      spec:
      selector:
         app: soap-oci-queue-app
      ports:
         - port: 80
            targetPort: 8080
      type: LoadBalancer
      
  8. Exécutez la commande kubectl dans le dossier où vous avez enregistré le fichier manifeste.

    kubectl apply -f springboot_application.yaml
    

    Maintenant, l'application est déployée et le service d'équilibreur de charge entrant est créé dans OKE.

    Appliquer le manifeste dans OKE

  9. Pour valider le pod et le service créés dans OKE, exécutez la commande suivante.

    kubectl get pods -A
    

    OKE PODS

    kubectl get svc -A
    

    Services OKE

    Note : Téléchargez le projet d'application Java Spring Boot basé sur Oracle GraalVM à partir d'ici : tutorial.zip.

Tâche 7 : Tester l'application Oracle Graal VM Spring Boot à l'aide de JMeter

Pour plus d'informations sur l'installation de JMeter, voir Introduction à JMeter.

Une fois JMeter installé et configuré, vous pouvez envoyer des demandes SOAP HTTP POST. Par exemple, réglez le nombre d'unités d'exécution à 2 pour représenter 2 utilisateurs ou applications simultanés, et réglez le nombre de boucles à 3000, ce qui signifie que chaque utilisateur ou application enverra 3000 demandes, pour un total de 6000 demandes SOAP.

Messages SOAP

Dans JMeter, définissez l'adresse IP de l'équilibreur de charge OCI, le chemin configuré dans le projet Spring Boot et le code SOAP XML dans le corps.

Demande SOAP HTTP

Exécutez JMeter avec 6000 transactions SOAP et vérifiez.

Note : Comme nous simulons la messagerie SOAP des applications client, pour chaque demande HTTP SOAP, les informations sont les mêmes que celles affichées dans le fichier XML SOAP indiqué ci-dessus et ne changent pas, mais dans un environnement client réel, les informations varient sûrement.

Exécutez l'instruction suivante :

  1. Pour voir le total des données stockées dans DAV.

    Oracle ATP

  2. Pour voir les détails des données stockées dans chaque table du DAV.

    • VOITURES :

      VOITURES

    • MAISONS :

      MAISONS

    • UTILISATEURS :

      UTILISATEURS

  3. Pour voir le nombre total de demandes de file d'attente OCI stockées dans la file d'attente OCI.

    Nombre total de demandes de file d'attente OCI

  4. Pour voir les détails du message dans la file d'attente OCI au format JSON.

    Détails des messages de file d'attente OCI

Remerciements

Autres ressources d'apprentissage

Explorez d'autres laboratoires sur le site docs.oracle.com/learn ou accédez à plus de contenu d'apprentissage gratuit sur le canal Oracle Learning YouTube. De plus, visitez education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

Pour obtenir la documentation sur le produit, visitez Oracle Help Center.