Client fonctionnel communiquant avec tous les MS

This commit is contained in:
TestAccountsUser 2018-03-18 02:49:08 +01:00
parent 717edf9812
commit f272e9baa8
23 changed files with 683 additions and 7 deletions

View File

@ -22,6 +22,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M8</spring-cloud.version>
</properties>
<dependencies>
@ -40,6 +41,11 @@
<version>4.0.0-2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -48,6 +54,18 @@
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
@ -57,5 +75,16 @@
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -2,8 +2,10 @@ package com.clientui;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients("com.clientui")
public class ClientUiApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,71 @@
package com.clientui.beans;
import java.util.Date;
public class CommandeBean {
private int id;
private Integer productId;
private Date dateCommande;
private Integer quantite;
private Boolean commandePayee;
public CommandeBean() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Date getDateCommande() {
return dateCommande;
}
public void setDateCommande(Date dateCommande) {
this.dateCommande = dateCommande;
}
public Integer getQuantite() {
return quantite;
}
public void setQuantite(Integer quantite) {
this.quantite = quantite;
}
public Boolean getCommandePayee() {
return commandePayee;
}
public void setCommandePayee(Boolean commandePayee) {
this.commandePayee = commandePayee;
}
@Override
public String toString() {
return "CommandeBean{" +
"id=" + id +
", productId=" + productId +
", dateCommande=" + dateCommande +
", quantite=" + quantite +
", commandePayee=" + commandePayee +
'}';
}
}

View File

@ -0,0 +1,58 @@
package com.clientui.beans;
public class PaiementBean {
private int id;
private Integer idCommande;
private Double montant;
private Long numeroCarte;
public PaiementBean() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getIdCommande() {
return idCommande;
}
public void setIdCommande(Integer idCommande) {
this.idCommande = idCommande;
}
public Double getMontant() {
return montant;
}
public void setMontant(Double montant) {
this.montant = montant;
}
public Long getNumeroCarte() {
return numeroCarte;
}
public void setNumeroCarte(Long numeroCarte) {
this.numeroCarte = numeroCarte;
}
@Override
public String toString() {
return "PaiementBean{" +
"id=" + id +
", idCommande=" + idCommande +
", montant=" + montant +
", numeroCarte=" + numeroCarte +
'}';
}
}

View File

@ -0,0 +1,69 @@
package com.clientui.beans;
public class ProductBean {
private int id;
private String titre;
private String description;
private String image;
private Double prix;
public ProductBean() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitre() {
return titre;
}
public void setTitre(String titre) {
this.titre = titre;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Double getPrix() {
return prix;
}
public void setPrix(Double prix) {
this.prix = prix;
}
@Override
public String toString() {
return "ProductBean{" +
"id=" + id +
", titre='" + titre + '\'' +
", description='" + description + '\'' +
", image='" + image + '\'' +
", prix=" + prix +
'}';
}
}

View File

@ -1,18 +1,124 @@
package com.clientui.controller;
import com.clientui.beans.CommandeBean;
import com.clientui.beans.PaiementBean;
import com.clientui.beans.ProductBean;
import com.clientui.proxies.MicroserviceCommandeProxy;
import com.clientui.proxies.MicroservicePaiementProxy;
import com.clientui.proxies.MicroserviceProduitsProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.RestTemplate;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@Controller
public class ClientController {
@Autowired
private MicroserviceProduitsProxy ProduitsProxy;
@Autowired
private MicroserviceCommandeProxy CommandesProxy;
@Autowired
private MicroservicePaiementProxy paiementProxy;
/*
* Étape (1)
* Opération qui récupère la liste des produits et on les affichent dans la page d'accueil.
* Les produits sont récupérés grâce à ProduitsProxy
* On fini par rentourner la page Accueil.html à laquelle on passe la liste d'objets "produits" récupérés.
* */
@RequestMapping("/")
public String accueil(Model model){
List<ProductBean> produits = ProduitsProxy.listeDesProduits();
model.addAttribute("produits", produits);
return "Accueil";
}
/*
* Étape (2)
* Opération qui récupère les détails d'un produit
* On passe l'objet "produit" récupéré et qui contient les détails en question à FicheProduit.html
* */
@RequestMapping("/details-produit/{id}")
public String ficheProduit(@PathVariable int id, Model model){
ProductBean produit = ProduitsProxy.recupererUnProduit(id);
model.addAttribute("produit", produit);
return "FicheProduit";
}
/*
* Étape (3) et (4)
* Opération qui fait appel au microservice de commande pour placer une commande et récupérer les détails de la commande créée
* */
@RequestMapping(value = "/commander-produit/{idProduit}/{montant}")
public String passerCommande(@PathVariable int idProduit, @PathVariable Double montant, Model model){
CommandeBean commande = new CommandeBean();
//On renseigne les propriétés de l'objet de type CommandeBean que nous avons crée
commande.setProductId(idProduit);
commande.setQuantite(1);
commande.setDateCommande(new Date());
//appel du microservice commandes grâce à Feign et on récupère en retour les détails de la commande créée, notamment son ID (étape 4).
CommandeBean commandeAjoutee = CommandesProxy.ajouterCommande(commande);
//on passe à la vue l'objet commande et le montant de celle-ci afin d'avoir les informations nécessaire pour le paiement
model.addAttribute("commande", commandeAjoutee);
model.addAttribute("montant", montant);
return "Paiement";
}
/*
* Étape (5)
* Opération qui fait appel au microservice de paiement pour traiter un paiement
* */
@RequestMapping(value = "/payer-commande/{idCommande}/{montantCommande}")
public String payerCommande(@PathVariable int idCommande, @PathVariable Double montantCommande, Model model){
PaiementBean paiementAExcecuter = new PaiementBean();
//on reseigne les détails du produit
paiementAExcecuter.setIdCommande(idCommande);
paiementAExcecuter.setMontant(montantCommande);
paiementAExcecuter.setNumeroCarte(numcarte()); // on génère un numéro au hasard pour simuler une CB
// On appel le microservice et (étape 7) on récupère le résultat qui est sous forme ResponseEntity<PaiementBean> ce qui va nous permettre de vérifier le code retour.
ResponseEntity<PaiementBean> paiement = paiementProxy.payerUneCommande(paiementAExcecuter);
Boolean paiementAccepte = false;
//si le code est autre que 201 CREATED, c'est que le paiement n'a pas pu aboutir.
if(paiement.getStatusCode() == HttpStatus.CREATED)
paiementAccepte = true;
model.addAttribute("paiementOk", paiementAccepte); // on envoi un Boolean paiementOk à la vue
return "confirmation";
}
//Génére une serie de 16 chiffres au hasard pour simuler vaguement une CB
private Long numcarte() {
return ThreadLocalRandom.current().nextLong(1000000000000000L,9000000000000000L );
}
}

View File

@ -0,0 +1,14 @@
package com.clientui.proxies;
import com.clientui.beans.CommandeBean;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "microservice-commandes", url = "localhost:9002")
public interface MicroserviceCommandeProxy {
@PostMapping(value = "/commandes")
CommandeBean ajouterCommande(@RequestBody CommandeBean commande);
}

View File

@ -0,0 +1,15 @@
package com.clientui.proxies;
import com.clientui.beans.PaiementBean;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "microservice-paiement", url = "localhost:9003")
public interface MicroservicePaiementProxy {
@PostMapping(value = "/paiement")
ResponseEntity<PaiementBean> payerUneCommande(@RequestBody PaiementBean paiement);
}

View File

@ -0,0 +1,25 @@
package com.clientui.proxies;
import com.clientui.beans.ProductBean;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
import java.util.Optional;
@FeignClient(name = "microservice-produits", url = "localhost:9001")
public interface MicroserviceProduitsProxy {
@GetMapping(value = "/Produits")
List<ProductBean> listeDesProduits();
/*
* Notez ici la notation @PathVariable("id") qui est différente de celle qu'on utlise dans le contrôleur
**/
@GetMapping( value = "/Produits/{id}")
ProductBean recupererUnProduit(@PathVariable("id") int id);
}

View File

@ -11,7 +11,20 @@
<div class="container">
<h1>Application Mcommerce</h1>
<h1 class="text-center" >Application Mcommerce</h1>
<div class="row">
<!--
Boucle sur tous les objets de type "produit" de la liste et affichage des informations produit.
-->
<div th:each="produit : ${produits}" class="col-md-4 my-1">
<a th:href="@{|/details-produit/${produit.id}|}" >
<img th:src="${produit.image}" class="card-img-top" />
<p th:text= "${produit.titre}"></p>
</a>
</div>
</div>
</div>

View File

@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Mcommerce</title>
<link rel="stylesheet" type="text/css"
href="http://localhost:8080/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center">Application Mcommerce</h1>
<div class="row">
<div class="col-md-4 mx-auto mt-5 text-center">
<p th:if="${paiementOk}" >
Paiement Accepté
</p>
<p th:unless="${paiementOk}">
Le paiement n'a pas abouti
</p>
</div>
</div>
</div>
<script type="text/javascript" src="http://localhost:8080/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Mcommerce</title>
<link rel="stylesheet" type="text/css"
href="http://localhost:8080/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center">Application Mcommerce</h1>
<div class="row">
<div class="col-md-4 mx-auto mt-5 text-center">
<img th:src="${produit.image}" class="card-img-top"/>
<p th:text="${produit.titre}" class="font-weight-bold"></p>
<p th:text="${produit.description}"></p>
<p>
<a th:href="@{|/commander-produit/${produit.id}/${produit.prix}||}" class="font-weight-bold">COMMANDER</a>
</p>
</div>
</div>
</div>
<script type="text/javascript" src="http://localhost:8080/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Mcommerce</title>
<link rel="stylesheet" type="text/css"
href="http://localhost:8080/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center">Application Mcommerce</h1>
<div class="row">
<div class="col-md-4 mx-auto mt-5 text-center">
<p>
Ici l'utilisateur sélectionne en temps normal un moyen de paiement et entre les informations de sa carte bancaire.<br/>
Nous allons éviter d'ajouter les formulaires nécessaireS afin de garder l'application la plus basique et simple possible pour la suite.<br/>
Si vous vous sentez à l'aise, vous pouvez créer un formulaire pour accepter le numéro de la CB, que vous traiterez dans le contrôleur grâce à
un <i>PostMapping</i>.
</p>
<!-- On passe l'id de la commande ET le montant de celle-ci afin que le contrôleur ait les informations nécessaires pour faire appel au microservice de paiement -->
<p>
<a th:href="@{|/payer-commande/${commande.id}/${montant}|}" class="font-weight-bold">Payer Ma Commande</a>
</p>
</div>
</div>
</div>
<script type="text/javascript" src="http://localhost:8080/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -37,4 +37,15 @@ public class CommandeController {
return commande;
}
/*
* Permet de mettre à jour une commande existante.
* save() mettra à jours uniquement les champs renseignés dans l'objet commande reçu. Ainsi dans ce cas, comme le champs date dans "commande" n'est
* pas renseigné, la date précédemment enregistrée restera en place
**/
@PutMapping(value = "/commandes")
public void updateCommande(@RequestBody Commande commande) {
commandesDao.save(commande);
}
}

View File

@ -1,3 +1,4 @@
spring.application.name=microservice-commandes
server.port 9002

View File

@ -22,6 +22,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M8</spring-cloud.version>
</properties>
<dependencies>
@ -42,6 +43,11 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -49,6 +55,18 @@
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
@ -58,5 +76,15 @@
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -2,8 +2,10 @@ package com.mpaiement;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients("com.mpaiement")
public class MpaiementApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,70 @@
package com.mpaiement.beans;
import java.util.Date;
public class CommandeBean {
private int id;
private Integer productId;
private Date dateCommande;
private Integer quantite;
private Boolean commandePayee;
public CommandeBean() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Date getDateCommande() {
return dateCommande;
}
public void setDateCommande(Date dateCommande) {
this.dateCommande = dateCommande;
}
public Integer getQuantite() {
return quantite;
}
public void setQuantite(Integer quantite) {
this.quantite = quantite;
}
public Boolean getCommandePayee() {
return commandePayee;
}
public void setCommandePayee(Boolean commandePayee) {
this.commandePayee = commandePayee;
}
@Override
public String toString() {
return "CommandeBean{" +
"id=" + id +
", productId=" + productId +
", dateCommande=" + dateCommande +
", quantite=" + quantite +
", commandePayee=" + commandePayee +
'}';
}
}

View File

@ -15,14 +15,14 @@ public class Paiement {
@Column(unique = true)
private Integer idCommande;
private Integer montant;
private Double montant;
private Long numeroCarte;
public Paiement() {
}
public Paiement(int id, Integer idCommande, Integer montant, Long numeroCarte) {
public Paiement(int id, Integer idCommande, Double montant, Long numeroCarte) {
this.id = id;
this.idCommande = idCommande;
this.montant = montant;
@ -45,11 +45,11 @@ public class Paiement {
this.idCommande = idCommande;
}
public Integer getMontant() {
public Double getMontant() {
return montant;
}
public void setMontant(Integer montant) {
public void setMontant(Double montant) {
this.montant = montant;
}

View File

@ -0,0 +1,20 @@
package com.mpaiement.proxies;
import com.mpaiement.beans.CommandeBean;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Optional;
@FeignClient(name = "microservice-commandes", url = "localhost:9002")
public interface MicroserviceCommandeProxy {
@GetMapping(value = "/commandes/{id}")
Optional<CommandeBean> recupererUneCommande(@PathVariable("id") int id);
@PutMapping(value = "/commandes")
void updateCommande(@RequestBody CommandeBean commande);
}

View File

@ -1,7 +1,9 @@
package com.mpaiement.web.controller;
import com.mpaiement.beans.CommandeBean;
import com.mpaiement.dao.PaiementDao;
import com.mpaiement.model.Paiement;
import com.mpaiement.proxies.MicroserviceCommandeProxy;
import com.mpaiement.web.exceptions.PaiementExistantException;
import com.mpaiement.web.exceptions.PaiementImpossibleException;
import org.springframework.beans.factory.annotation.Autowired;
@ -9,12 +11,20 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
@RestController
public class PaiementController {
@Autowired
PaiementDao paiementDao;
@Autowired
MicroserviceCommandeProxy microserviceCommandeProxy;
/*
* Opération pour enregistrer un paiement et notifier le microservice commandes pour mettre à jour le statut de la commande en question
**/
@PostMapping(value = "/paiement")
public ResponseEntity<Paiement> payerUneCommande(@RequestBody Paiement paiement){
@ -26,13 +36,22 @@ public class PaiementController {
//Enregistrer le paiement
Paiement nouveauPaiement = paiementDao.save(paiement);
// si le DAO nous retourne null c'est que il ya eu un problème lors de l'enregistrement
if(nouveauPaiement == null) throw new PaiementImpossibleException("Erreur, impossible d'établir le paiement, réessayez plus tard");
//On récupère la commande correspondant à ce paiement en faisant appel au Microservice commandes
Optional<CommandeBean> commandeReq = microserviceCommandeProxy.recupererUneCommande(paiement.getIdCommande());
//commandeReq.get() permet d'extraire l'objet de type CommandeBean de Optional
CommandeBean commande = commandeReq.get();
//TODO Nous allons appeler le Microservice Commandes ici pour lui signifier que le paiement est accepté
//on met à jour l'objet pour marquer la commande comme étant payée
commande.setCommandePayee(true);
//on envoi l'objet commande mis à jour au microservice commande afin de mettre à jour le status de la commande.
microserviceCommandeProxy.updateCommande(commande);
//on renvoi 201 CREATED pour notifier le client au le paiement à été enregistré
return new ResponseEntity<Paiement>(nouveauPaiement, HttpStatus.CREATED);
}

View File

@ -1,3 +1,4 @@
spring.application.name=microservice-paiement
server.port 9003

View File

@ -1,3 +1,4 @@
spring.application.name=microservice-produits
server.port 9001