prérequis: Pour cristalliser les concepts microservices, il est supposé que les composants suivants sont installés dans votre ordinateur.
- JDK 1.8: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
- Spring Tool Suite 3.7.2 (STS): https://spring.io/tools/sts/all
- Maven 3.3.1: https://maven.apache.org/download.cgi
- Rabbit MQ sera également nécessaire pour cet exemple. Téléchargez et installez la dernière version de Rabbit MQ ici https://www.rabbitmq.com/download.html et suivez les étapes d'installation documentées sur le site. Une fois prêt, démarrez le serveur RabbitMQ via la commande suivante: $./ rabbitmq-server ou plus simple encore via Windows Services. Vous pouvez également installer une interface web pour accéder RabbitMq en suivant ce guide (en anglais): https://cmatskas.com/getting-started-with-rabbitmq-on-windows/
Dans cet exemple, deux microservices (deux projets jar), le Customer Profile et l'autre, le Customer Notification seront développés:
Comme l'indique le diagramme, le microservice Customer Profile expose des méthodes (CRUD)pour créer(Create), lire(Read), mettre-à-jour(Update) et supprimer(Delete) un Customer en Base de donnees. Le processus d'enregistrement applique une certaine logique métier(Business logic), enregistre le client et envoie un message au microservice Customer notification. Le microservice Customer Notification accepte le message envoyé par le service d'enregistrement et envoie un message électronique au client en utilisant un serveur SMTP.
Le diagramme de modèle de domaine de classe de microservices client est le suivant:
CustomerController dans le diagramme est le REST-endpoint, qui invoque une classe de composante, CustomerComponent (la classe CustomerRegistrar.java annotée @Component). Le composant classe/bean gère toute la logique métier. CustomerRepository est un référentiel Spring Data JPA défini pour gérer la persistance de l'entité Customer.
Codes Sources: Dans cette exemple nous ferrons converser deux applications Spring Boot (deux fichiers jar). Vous pouvez donc télécharger les codes sources complets via github et les importer dans votre Editeur (STS, Eclipse ...)
- Customer : https://github.com/Georges73/springbootRabbitMq_1_1
- customernotification https://github.com/Georges73/springbootRabbitMqReceiver_1_2
Vous pouvez également suivre manuellement les étapes suivantes :
- Créez un nouveau projet Spring Boot et appelez-le commevousvoulez.customer, de la même manière qu'ici. Sélectionnez les options comme dans la capture d'écran suivante dans l'écran de sélection du module de démarrage:
La structure du projet sera similaire à la capture d'écran suivante:
3. Commencez à créer l'application en ajoutant une classe d'entité nommée Customer. Pour simplifier, il n'y a que trois champs ajoutés à la classe Entité client: le champ ID autogénéré, le nom(name) et le courrier électronique(email). Jetez un coup d'œil au code suivant:
@Entity class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String email; public Customer (){} public Customer(String name, String email) { super(); this.name = name; this.email = email; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", email=" + email + "]"; }
4. Ajoutez une classe de repository pour gérer la gestion de la persistance du Customer. CustomerRepository.java étend(extends) le référentiel JpaRepository . Cela signifie que toutes les méthodes CRUD et les méthodes de recherche par défaut sont automatiquement implémentées par le référentiel Spring Data JPA, comme suit:
@RepositoryRestResource @Lazy interface CustomerRespository extends JpaRepository{ Optional findByName(@Param("name") String name); }
Dans cet exemple, nous avons ajouté une nouvelle méthode à la classe de repository, findByName(), qui recherche essentiellement le client en fonction du nom du client et renvoie un objet Customer s'il existe.
4. L'annotation @RepositoryRestResource permet l'accès au repository via les services RESTful. Cela activera également HATEOAS et HAL par défaut. Comme pour les méthodes CRUD il n'ya pas de logique supplémentaire à ajouter, nous allons laisser comme il est sans contrôleur ou des classes de composants. L'utilisation de HATEOAS nous aidera à naviguer sans difficulté dans les méthodes du Customer repository. Beaucoup plus simple et clair donc car moins de verbiages.
Notez qu'il n'y a aucune configuration ajoutée n'importe où pour pointer vers n'importe quelle base de données. Comme les bibliothèques H2 sont dans la class path, toute la configuration est effectuée par défaut par Spring Boot en fonction de la configuration automatique H2. En d'autre termes, lorsque Spring Boot démarrera le projet, il détectera H2 dans le fichier pom.xml localisé dans la classe path et se chargera du reste. Oui, Spring boot fait ca. Fini les longues et fastidieuses configuration de pour établir une connexion avec une base de données.
5. Mettez à jour le fichier Application.java en ajoutant CommandLineRunner pour initialiser le repository avec certains données(name, email) Customer, comme suit:
@RepositoryRestResource @SpringBootApplication @EnableRabbit public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean CommandLineRunner init(CustomerRespository customerRepository) { return (evt) -> { customerRepository.save(new Customer("Adam","adam@boot.com")); customerRepository.save(new Customer("John","john@boot.com")); customerRepository.save(new Customer("Smith","smith@boot.com")); customerRepository.save(new Customer("Edgar","edgar@boot.com")); customerRepository.save(new Customer("Martin","martin@boot.com")); customerRepository.save(new Customer("Tom","tom@boot.com")); customerRepository.save(new Customer("Sean","sean@boot.com")); }; } }
- CommandLineRunner, défini comme un @bean, indique qu'il doit s'exécuter lorsqu'il est contenu dans SpringApplication. Cela va insérer les six exemples de donnees Customer dans la base de données au démarrage.
- À ce stade, exécutez l'application en tant que Spring boot app (run as spring boot app de la même manière qu'ici.). Ouvrez le navigateur HAL et pointez le navigateur vers http://localhost:8080.
- dans la section Explorer de votre navigateur HAL vous devez copier et coller : http://localhost:8080/customers et cliquer sur Go. Cette action va répertorier tous les customers dans la section Response Body du navigateur HAL
6. À l'étape suivante, ajoutez une classe contrôleur, CustomerController.java, pour gérer les noeuds finaux de service. Il n'y a qu'un seul point d'extrémité (End-point)dans cette classe, /register, qui est utilisé pour enregistrer un Customer. En cas de succès, il renvoie l'objet Customer comme réponse, comme suit:
@RestController class CustomerController{ CustomerRegistrar customerRegistrar; @Autowired CustomerController(CustomerRegistrar customerRegistrar){ this.customerRegistrar = customerRegistrar; } @RequestMapping( path="/register", method = RequestMethod.POST) Customer register(@RequestBody Customer customer){ return customerRegistrar.register(customer); } }
7. Un composant CustomerRegistrar.java est ajouté pour gérer la logique métier. Dans ce cas, la logique métier est limitée au composant. Dans cette classe de composants, tout en enregistrant un Customer, nous vérifierons simplement si le nom du client existe déjà dans la base de données ou non. Si elle n'existe pas, nous allons insérer un nouvel enregistrement, sinon nous enverrons un message d'erreur, comme suit:
@RestController @Component @Lazy class CustomerRegistrar { CustomerRespository customerRespository; Sender sender; @Autowired CustomerRegistrar(CustomerRespository customerRespository, Sender sender){ this.customerRespository = customerRespository; this.sender = sender; } Customer register(Customer customer){ OptionalexistingCustomer = customerRespository.findByName(customer.getName()); if (existingCustomer.isPresent()){ throw new RuntimeException("is already exists"); } else { customerRespository.save(customer); sender.send(customer.getEmail()); } return customer; } }
8. Vous pouvez redémarrer votre application Spring boot et tapez l'URL localhost:8080/ dans votre navigateur de choix. cela ouvrira votre votre navigateur HAL
9. Dans votre interface HAL, tapez : http://localhost:8080/customers dans le champs Explorer et observer le resultat dans la section Links comme suit:
10. Cliquez maintenant sur le premier bouton orange dans la colonne NON-GET intersection self. Cette action vous ouvrira un formulaire pour creer un nouveau client (Customer). Comme suit:
11. Remplissez le formulaire et modifiez le champ action comme indiqué dans le diagramme. Cliquez sur le bouton Make Request. Cela appellera le service de register du controller et enregistrera le client. Essayez de donner un nom déjà existant comme par exemple : Edgar ,edgar@boot.com pour tester si le message d'erreur fonctionne .
12. Attaquons maintenant la dernière partie de l'exemple en intégrant le Customer Notification service (notre deuxième application Spring Boot que vous avez téléchargé) pour informer le client. Lorsque l'inscription est réussie, envoyez un e-mail au client en appelant de façon asynchrone le microservice de notification customer.
13. D'abord mettez à jour CustomerRegistrar.java (si cela n'est pas deja le cas) pour appeler le deuxième microservice. Cela se fait par messagerie (messaging). Dans ce cas, nous avons injecté un composant émetteur (sender) pour envoyer une notification au client en transmettant l'adresse électronique du client à l'expéditeur, comme suit:
@RestController
@Component
@Lazy
class CustomerRegistrar {
CustomerRespository customerRespository;
Sender sender;
@Autowired
CustomerRegistrar(CustomerRespository customerRespository, Sender sender){
this.customerRespository = customerRespository;
this.sender = sender;
}
Customer register(Customer customer){
Optional existingCustomer = customerRespository.findByName(customer.getName());
if (existingCustomer.isPresent()){
throw new RuntimeException("is already exists");
} else {
customerRespository.save(customer);
sender.send(customer.getEmail());
}
return customer;
}
}
14. Le composant émetteur(sender) sera basé sur RabbitMQ et AMQP. Dans cet exemple, RabbitMessagingTemplate (org.springframework.amqp.rabbit.core.RabbitMessagingTemplate) est utilisé . Jetez un oeil à ce qui suit:
@Component
@Lazy
class Sender {
RabbitMessagingTemplate template;
@Autowired
Sender(RabbitMessagingTemplate template){
this.template = template;
}
@Bean
Queue queue() {
return new Queue("CustomerQ", false);
// le serveur RabbitMq surveillera les activites de notre
// application grace à l'attribut "CustomerQ".
}
public void send(String message){
template.convertAndSend("CustomerQ", message);
}
}
L'annotation @Lazy est utile car il aide à augmenter le temps de démarrage de l'application boot car, comme vous le savez probablement, lors du démarrage d une application Spring, chaque bean doit etre construit dans le contexte Spring. cela prend du temps Hors avec @Lazy cela ne sera initialisés uniquement lorsque le besoin s'en fait sentir. C-a-d lorsque la classe Sender sera instancie pour faire son job.
15. Nous allons également mettre à jour le fichier application.properties pour inclure les propriétés liées à Rabbit MQ, En effet, RabbitMq que vous avez installe dans votre ordinateur surveillera toutes les activités de votre application grace à l'attribut "CustomerQ" mais via quel canal ? Comment RabbitMq est au courant de votre application qui tourne dans votre ordinateur ? He bien via le port numéro 5672 (port par défaut de rabbitMq) comme suit:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
Ok, nous venons de parcourir le premier module Customer Profile Service de notre microservice.
Cela veut dire que nous sommes désormais capable de créer un Customer et de sauvegarder ses données dans la base de données H2. Ce que nous voulons maintenant c'est de créer un deuxième module Customer Notification service qui aura pour but de notifier le customer que son inscription a bel et bien été complété. Alors la question qu on peut se poser c'est pourquoi faut-il un deuxième module alors qu il suffirait de tout implémenter dans la même application monolithique. He bien c'est cela la même le principe Microserves. Séparer tout ce qui peut être séparé afin de limiter interdépendance entre chaque composantes ou Diviser pour régner.
16. Nous sommes prêts à envoyer le message. Pour consommer le message et envoyer des e-mails, nous allons créer un service de notification. Pour cela, créons un autre microservice Spring Boot, chapitre2.Bootcustomernotification (notre deuxième application Spring Boot que vous avez téléchargé).
17, Ajoutez une classe de Receiver.java. La classe Receiver attend les messages de Customer(Sender). Celui-ci recevra un message envoyé par le Customer Profil service . À l'arrivée d'un message, il enverra un e-mail, comme suit:
@Component
class Receiver {
@Autowired
Mailer mailer;
@Bean
Queue queue() {
return new Queue("CustomerQ", false);
}
@RabbitListener(queues = "CustomerQ")
public void processMessage(String email) {
System.out.println(email);
mailer.sendMail(email);
}
}
18. Ajoutez un autre composant pour envoyer un e-mail au client. Nous utiliserons JavaMailSender (org.springframework.mail.javamail.JavaMailSender) pour envoyer un e-mail via le code suivant:
@Component
class Mailer {
@Autowired
private JavaMailSender javaMailService;
Mailer( ){
}
public void sendMail(String email){
System.err.println(email);
SimpleMailMessage mailMessage=new SimpleMailMessage();
mailMessage.setTo(email);
mailMessage.setSubject("Registration");
mailMessage.setText("Successfully Registered");
javaMailService.send(mailMessage);
}
}
19. Pour verifier SMTP, une configuration est nécessaire pour vous assurer que les mails sortent bien.
Dans cet exemple, FakeSMTP sera utilisé. Vous pouvez télécharger FakeSMTP depuis https://nilhcem.github.io/FakeSMTP/.
Une fois que vous avez téléchargé fakeSMTP-2.0.Jar, exécutez le serveur SMTP en exécutant la commande suivante: java-jar fakeSMTP-2.0.jar ou bien double cliquez sur le fichier jar que vous avez téléchargé. Cela ouvrira une interface GUI pour monitorer les messages emails. Clickez sur le bouton start Server just à cote de la textbox listening port.
20. Mettez à jour application.properties avec les paramètres de configuration suivants pour se à RabbitMQ ainsi qu'au serveur de messagerie fakeSMTP-2.0:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.mail.host=localhost
spring.mail.port=2525
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.mail.host=localhost
spring.mail.port=2525
21. Nous sommes prêts à tester nos microservices de bout en bout. Démarrez les deux applications Spring Boot. Ouvrez le navigateur et répétez les étapes de création du customer (revoir étapes 8,9,10 et 11)via le navigateur HAL. Dans ce cas, immédiatement après la soumission de la demande, nous serons en mesure de voir le courrier électronique dans l'interface graphique fakeSMTP-2.0. À l'interne, le service Profil de client appelle de façon asynchrone le service Notification du client qui, à son tour, envoie le message électronique au serveur SMTP:
Important: La section Listening port doit absolument correspondre avec le port spring.mail.port=2525 indique dans l’étape précédente (20).