• 8 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 08/08/2023

Créez les microservices e-commerce et leur client

Mettez en place l'application "Mcommerce"

Afin de vous aider à mieux comprendre les Edge Microservices, nous allons commencer par créer une petite application e-commerce ultraminimaliste que nous allons appeler "Mcommerce".

Cette application est composée de 3 microservices :

  1. Microservice-produits : ce microservice gère le produit. Il propose 2 opérations simples : lister tous les produits, et récupérer un produit par son ID.

  2. Microservice-commandes : microservice de gestion des commandes. Il permet de passer une commande et de récupérer une commande par son ID.

  3. Microservice-paiements : ce microservice permet de simuler le paiement d'une commande. Une fois le paiement enregistré, il fait appel au Microservice-commandes pour mettre à jour le statut de la commande.

Nous allons commencer par mettre en place notre application dans IntelliJ IDEA.

Commencez par cloner le projet vers un dossier de votre choix.

git clone

Une fois le projet cloné, cliquez sur "Import Project", puis sélectionnez le dossier "mcommerce". Sélectionnez "Create project from existing sources" et sélectionnez un pom :

Puis sélectionnez Module from Existing Sources :

 

Et sélectionnez les deux autres poms :

Vous devriez obtenir :

 

Cette forme de projet , assez spéciale dans IntelliJ, fait que le projet est constitué de plusieurs modules. Ces modules sont des microservices, dans notre cas.

L'avantage est que chaque module est un projet en soi. Il a ses propres dépendances, ses propres fichiers de configuration et surtout, vous allez pouvoir les exécuter tous simultanément, comme si vous aviez ouvert trois projets IntelliJ différents.

Vous pourrez ainsi avoir votre projet localisé à un seul endroit, tout en gardant vos microservices parfaitement isolés. Vous pourrez également les lancer dans la même fenêtre et les faire communiquer, sans jongler entre plusieurs projets IntelliJ différents.

Changez de branche dans le projet vers "TestBranch", spécialement créé pour que vous puissiez vous familiariser avec le passage de branche en branche (non, je ne parle pas de singes) dans IntelliJ. Tout en bas à droite, sélectionnez origin/TestBranch -> Checkout as new local branch :

Nommez ensuite du même nom votre copie de cette branche "TestBranch" dans la boîte de dialogue qui s'ouvre. 

Vous êtes désormais sur la branche "TestBranch". Vérifiez que c'est bien le cas, en bas à droite :

 

Explorez l'application

Nous allons analyser les différents microservices afin que vous soyez à l'aise pour les manipuler durant le cours.

Tous ces microservices ont en commun :

  • l'utilisation de Spring Data JPA pour la communication avec la base de données ;

  • une base de données en mémoire de type H2 ;

  • les mêmes paramètres dans le fichier application.properties :

server.port 9001 #Configurations H2 spring.jpa.show-sql=true 
spring.h2.console.enabled=true #défini l'encodage pour data.sql 
spring.datasource.sql-script-encoding=UTF-8

Seul server.port change. Chaque microservice a son propre port.

Analysez le Microservice Produits

Ce microservice permet une gestion très basique des produits.

package com.mproduits.web.controller;

import com.mproduits.dao.ProductDao;
import com.mproduits.model.Product;
import com.mproduits.web.exceptions.ProductNotFoundException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;

@RestController
public class ProductController {

  private final ProductDao productDao;

  public ProductController(ProductDao productDao){
      this.productDao = productDao;
  }
 
  // Affiche la liste de tous les produits disponibles
  @GetMapping(value = "/Produits")
  public List<Product> listeDesProduits(){

      List<Product> products = productDao.findAll();

      if(products.isEmpty()) throw new ProductNotFoundException("Aucun produit n'est disponible à la vente");

      return products;

  }

  //Récuperer un produit par son id
  @GetMapping( value = "/Produits/{id}")
  public Optional<Product> recupererUnProduit(@PathVariable int id) {

      Optional<Product> product = productDao.findById(id);

      if(!product.isPresent())  throw new ProductNotFoundException("Le produit correspondant à l'id " + id + " n'existe pas");

      return product;
  }
}

Microservice-produits écoute le port 9001. Il est constitué des éléments suivants :

  • La méthode    listeDesProduits  , qui permet la récupération de la liste de tous les produits.

  • La méthode    recupererUnProduit  , qui permet de récupérer un produit par son ID.

  • Une exception   ProductNotFoundException  , qui renvoie le code 404 si le ou les produits ne sont pas trouvés.

  • Le fichier data.sql , qui permet de préremplir automatiquement la base de données avec plusieurs produits, afin de pouvoir faire des tests.

Analysez le Microservice Commandes

Ce microservice permet de passer des commandes et d'en récupérer :

package com.mcommandes.web.controller;


import com.mcommandes.dao.CommandesDao;
import com.mcommandes.model.Commande;
import com.mcommandes.web.exceptions.CommandeNotFoundException;
import com.mcommandes.web.exceptions.ImpossibleAjouterCommandeException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController
public class CommandeController {

  private final CommandesDao commandesDao;

  public CommandeController(CommandesDao commandesDao){
      this.commandesDao = commandesDao;
  }
 
  @PostMapping (value = "/commandes")
  public ResponseEntity<Commande> ajouterCommande(@RequestBody Commande commande){

      Commande nouvelleCommande = commandesDao.save(commande);

      if(nouvelleCommande == null) throw new ImpossibleAjouterCommandeException("Impossible d'ajouter cette commande");

      return new ResponseEntity<Commande>(commande, HttpStatus.CREATED);
  }

  @GetMapping(value = "/commandes/{id}")
  public Optional<Commande> recupererUneCommande(@PathVariable int id){

      Optional<Commande> commande = commandesDao.findById(id);

      if(!commande.isPresent()) throw new CommandeNotFoundException("Cette commande n'existe pas");

      return commande;
  }
}

Microservice-commandes écoute le port 9002. Il est constitué des éléments suivants :

  • La méthode  ajouterCommande  , qui  permet l'ajout d'une commande via un POST.

  • La méthode  recupererUneCommande  , qui  récupère une commande via son ID.  Optional  permet de ne plus vérifier si l'objet est null à chaque fois, et évite les NullPointerExceptions. Vous pouvez en savoir plus ici.  isPresent  vérifie que l'objet commande existe et n'est pas vide.

  • L'exception   ImpossibleAjouterCommandeException  , qui est déclenchée en dernier recours quand on n'arrive pas à enregistrer la commande pour cause d'erreur interne. Le code renvoyé est alors 500.

  • L'exception  CommandeNotFoundException  , qui renvoie le code 404 lorsqu'une commande n'est pas trouvée.

Analysez le Microservice Paiement

Ce microservice reçoit l'ID d'une commande, le montant et le numéro de la carte bancaire, puis enregistre le paiement dans la base de données :

package com.mpaiement.web.controller;

import com.mpaiement.dao.PaiementDao;
import com.mpaiement.model.Paiement;
import com.mpaiement.web.exceptions.PaiementExistantException;
import com.mpaiement.web.exceptions.PaiementImpossibleException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
public class PaiementController {

  private final PaiementDao paiementDao;

  public PaiementController(PaiementDao paiementDao){
      this.paiementDao = paiementDao;
  }

  @PostMapping(value = "/paiement")
  public ResponseEntity<Paiement>  payerUneCommande(@RequestBody Paiement paiement){


      //Vérifions s'il y a déjà un paiement enregistré pour cette commande
      Paiement paiementExistant = paiementDao.findByidCommande(paiement.getIdCommande());
      if(paiementExistant != null) throw new PaiementExistantException("Cette commande est déjà payée");

      //Enregistrer le paiement
      Paiement nouveauPaiement = paiementDao.save(paiement);


      if(nouveauPaiement == null) throw new PaiementImpossibleException("Erreur, impossible d'établir le paiement, réessayez plus tard");



      //TODO Nous allons appeler le Microservice Commandes ici pour lui signifier que le paiement est accepté
      return new ResponseEntity<Paiement>(nouveauPaiement, HttpStatus.CREATED);

  }

}

Il dispose d'une seule opération :   payerUneCommande  . Une commande ne peut être payée qu'une seule fois, on vérifie alors si le paiement à effectuer n'a pas déjà eu lieu. Pour cela, nous devons chercher s'il y a un paiement correspondant à l'ID de commande idCommande. On crée donc une méthode dans PaiementDao

Paiement findByidCommande(int idCommande);

Si un paiement précédent est trouvé, on déclenche l'exception   PaiementExistantException  . Cette exception renvoie un code particulier, 409 CONFLICT , qui indique que les données reçues entrent en conflit avec des données existantes.

En cas d'impossibilité d'enregistrer le paiement, le code 500 est renvoyé.

En cas de succès, le code 201 Created est renvoyé, avec le contenu du paiement enregistré.

Découvrez ce que nous allons faire avec ces microservices

Voici un diagramme de l'application finale que nous souhaitons développer :

 Voici les 7 étapes décrites dans le diagramme. 1 : Proposition des produits. 2 : Sélection d'un produit. 3  Commande du produit. 4 : Récupération de la commande. 5 : Demande de paiement. 6 : Statut du paiement. 7 : Confirmation.

Créez un client

Nous allons maintenant créer notre squelette du client qui ira consommer nos microservices. Pour créer une interface graphique, nous allons utiliser Thymeleaf comme moteur de template.

Pour cela, nous allons créer une nouvelle branche nommée Thymeleaf.

Nous allons commencer par créer un client très minimaliste afin que vous vous familiarisiez avec l'utilisation de Thymeleaf (pour ceux qui ne connaissent pas), puis nous allons l'enrichir.

Commencez par créer un projet sur Spring Initializr, nommez-le client-ui, puis cochez "Web" et "Thymeleaf", comme suit :

Rendez-vous dans IntelliJ, et importez le projet comme nouveau module :

Créez un nouveau contrôleur "ClientController" sous un package "controller" :

Voici donc notre contrôleur :

package com.clientui.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller

public class ClientController 
{

  @RequestMapping("/")

  public String accueil(Model model)
  {

      return "Accueil";

  }



}

Explications :

  • L'annotation @Controller est une annotation de Spring MVC qui dit au DispatcherServlet, qui reçoit toutes les requêtes pour le dispatcher, de chercher dans cette classe s'il y a une opération qui correspond à l'URI appelé.

  • Nous créons ensuite une méthode qui répond aux URI de type "/", c'est-à-dire la page d'accueil de notre interface.

  • model est une instance de la classe Model, que l'on passera en argument à notre méthode, et qui nous permettra de renseigner des données à passer à la vue. Nous y reviendrons plus tard.

  • return "Accueil" : Spring ira chercher dans le dossier "template", dans "resources", la page HTML du nom de Accueil.html. 

Justement, rendez-vous dans resources/templates  et créez un fichier Accueil.html, puis écrivez quelque chose à l'intérieur du fichier. Lancez ensuite votre client :

 

Rendez-vous à http://localhost:8080/, et vous verrez le contenu de votre HTML s'afficher.

Nous allons utiliser Bootstrap pour créer notre interface. Pour faciliter son intégration, nous allons ajouter une dépendance à notre pom.xml :

<dependency>

 

         <groupId>org.webjars</groupId>

 

         <artifactId>bootstrap</artifactId>

 

         <version>4.0.0-2</version>

 

</dependency>

Cette dépendance rendra les fichiers de Bootstrap disponibles pour notre HTML, sans aucune configuration ou chemin à trouver.

À noter qu'il est possible d'utiliser la version hébergée par Google par exemple, mais comme nous souhaitons que notre microservice soit autonome, nous allons garder les fichiers nécessaires en local.

Ajoutez ensuite ce contenu HTML à Accueil.html :

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
   <title>Mcommerce</title>
   <link rel="stylesheet" type="text/css" href="webjars/bootstrap/4.0.0-2/css/bootstrap.min.css"/>
</head>

<body>
<div class="container">
   <h1>Application Mcommerce</h1>
</div>
<script type="text/javascript" src="webjars/bootstrap/4.0.0-2/js/bootstrap.min.js"></script>
</body>
</html>

Relancez le client et vérifiez que tout fonctionne correctement.

Nous allons maintenant mettre en place Feign pour simplifier nos appels HTTP entre nos services.

En résumé

  • Nous avons mis en place nos microservices et mise en place la base de notre front.

  • Spring Initializr permet de générer le squelette des projets.

Dans le prochain chapitre, vous allez apprendre à utiliser Feign pour faire communiquer vos Microservices. On y va !

Exemple de certificat de réussite
Exemple de certificat de réussite