Cours Java EE et Spring pour Développeurs
Cours Java EE et Spring pour Développeurs
JAVA EE
          GENIE LOGICIEL
INTRODUCTION
       Le Spring Framework, en revanche, propose une approche plus légère et flexible grâce à
des concepts comme l’Inversion de Contrôle (IoC) et l’Injection de Dépendances. Spring Boot,
une extension de Spring, simplifie le développement d'applications en fournissant des
configurations par défaut et en facilitant la création d'APIs RESTful.
Objectifs du Cours
Ce cours vise à :
   À l'issue de ce cours, les étudiants disposeront d'une base solide en développement Java, leur
permettant de relever les défis du monde professionnel.
Activité 1: Introduction à Java EE et aux Frameworks Modernes (Spring)
Objectifs de l’activité :
        Java EE (Enterprise Edition) est une extension de Java SE (Standard Edition) et une
plateforme robuste pour le développement d’applications d'entreprise. Elle propose un ensemble
d’API (Application Programming Interfaces) et de spécifications standardisées, facilitant la
création d’applications évolutives, sécurisées et robustes, adaptées aux environnements complexes
d'entreprise.
       Servlets : Composants Java utilisés pour gérer les requêtes HTTP dans les applications
        web.
       Java Server Pages (JSP) : Outil permettant de générer des pages HTML dynamiques,
        souvent utilisé avec les Servlets.
       Java Persistence API (JPA) : API standard pour la gestion des bases de données
        relationnelles via le mapping objet-relationnel.
       Enterprise JavaBeans (EJB) : Composants pour la gestion des transactions et des
        fonctionnalités de sécurité dans les systèmes distribués.
       Java Messaging Service (JMS) : API pour la communication asynchrone entre
        applications.
    Java EE suit une architecture en trois couches (ou "tiers") :
    1. Tier 1 - Côté client : Interface utilisateur qui interagit avec l'application (navigateur,
        mobile).
    2. Tier 2 - Serveur d'application : Contient la logique métier, comme la gestion des
        transactions et les services web.
    3. Tier 3 - Système de base de données : Gère la persistance des données.
       Inversion of Control (IoC) : Plutôt que le code contrôle ses dépendances, Spring gère la
        création et l’injection des objets nécessaires (injection de dépendances).
       AOP (Aspect-Oriented Programming) : Gestion transversale des aspects comme la
        sécurité ou la gestion des transactions sans affecter directement la logique métier.
       Spring Boot : Un sous-projet de Spring, qui permet de créer des applications rapidement
        avec des configurations minimales.
3. Les avantages de Spring par rapport à Java EE classique
3.2. Testabilité
        Démarrage rapide : Spring Boot inclut un serveur web embarqué (Tomcat par défaut) qui
         permet de lancer rapidement des applications, sans configuration complexe.
        Auto-configuration : Spring Boot auto-configure la plupart des composants en fonction
         des dépendances ajoutées, réduisant ainsi la charge sur les développeurs.
        Microservices : Avec l’essor des architectures microservices, Spring Boot est
         particulièrement adapté pour développer des services légers et indépendants.
4. Conclusion
      Java EE offre une architecture solide pour les applications d’entreprise avec un ensemble
       de spécifications standardisées.
      Spring apporte flexibilité, simplicité, et modularité, tout en offrant des outils comme
       Spring Boot qui accélèrent le développement.
      La testabilité et la modularité de Spring sont de véritables atouts pour les projets
       modernes.
Activité 2: Servlets, JSP et JavaBeans
Objectifs de l’activité :
       Comprendre le fonctionnement des Servlets et leur rôle dans le traitement des requêtes et
        des réponses HTTP.
       Découvrir JavaServer Pages (JSP) pour la génération dynamique de contenu web.
       Introduire les JavaBeans et l’utilisation de l'Expression Language (EL) pour simplifier
        l’accès aux données dans les pages JSP.
        Une Servlet est une classe Java qui étend les capacités des serveurs capables de répondre
aux requêtes HTTP. Elles sont principalement utilisées pour traiter les requêtes des clients et
générer des réponses. Les Servlets sont une partie centrale de la couche de présentation dans les
applications Java EE.
    1. Initialisation : La méthode init() est appelée une seule fois lorsque la Servlet est chargée
        en mémoire par le conteneur (ex: Tomcat, Jetty).
    2. Traitement des requêtes : La méthode service() gère les requêtes entrantes (souvent
        redéfinie via doGet() ou doPost() pour les requêtes spécifiques).
    3. Destruction : La méthode destroy() est appelée pour libérer les ressources lorsque la
        Servlet est arrêtée ou retirée du service.
1.3. Exécution d'une Servlet
         Voici un exemple d'implémentation d'une Servlet simple qui gère une requête HTTP GET
:
import   javax.servlet.*;
import   javax.servlet.http.*;
import   java.io.IOException;
import   java.io.PrintWriter;
Dans cet exemple, la Servlet reçoit une requête HTTP GET et renvoie une réponse HTML simple.
         Java Server Pages (JSP) est une technologie qui permet de générer dynamiquement des
pages web en combinant du code Java et du HTML. Elle permet d'inclure de la logique métier dans
les pages web tout en facilitant l’affichage du contenu dynamique généré par une application Java.
         Dans une page JSP, vous pouvez insérer du code Java au sein de balises spéciales <% %>.
JSP compile ces pages en Servlets lors de leur première exécution. Exemple de page JSP :
Ici, la variable nom est récupérée depuis une requête HTTP, puis affichée dans la page web.
        Les Servlets sont parfaits pour gérer la logique métier, mais pour l'affichage HTML, cela
peut devenir verbeux et difficile à maintenir. JSP simplifie ce processus en permettant d'écrire du
HTML et d'insérer des fragments de code Java seulement là où c'est nécessaire.
Un JavaBean est une classe Java ordinaire, mais elle suit une convention stricte :
    Les JavaBeans sont souvent utilisés pour encapsuler des données et les échanger entre
différentes couches d’une application (ex: de la couche métier vers la couche présentation).
public Utilisateur() {}
        Dans une page JSP, vous pouvez créer et utiliser des JavaBeans pour accéder et afficher
des données.
Exemple :
Ici, un objet Utilisateur est créé et ses propriétés sont définies à partir de la requête HTTP. Ces
propriétés peuvent ensuite être affichées dynamiquement dans la page.
        L’Expression Language (EL) simplifie l’accès aux objets comme les JavaBeans dans les
pages JSP. Plutôt que d’utiliser les balises JSP comme jsp:getProperty, EL permet d’accéder
aux propriétés directement à l’aide d’une syntaxe plus concise :
<h2>Nom: ${user.nom}</h2>
<h2>Email: ${user.email}</h2>
Grâce à EL, le code JSP devient plus lisible et plus facile à maintenir.
4. Conclusion
       Les Servlets et JSP sont des composants essentiels pour la création d'applications web en
Java EE, offrant une combinaison puissante pour la gestion des requêtes HTTP et la génération de
pages web dynamiques. L’introduction des JavaBeans permet une gestion plus efficace des
données, tandis que l'Expression Language (EL) facilite l'accès aux données dans les pages JSP.
Objectifs de l’activité :
        L'IoC est implémenté dans Spring via le conteneur IoC, qui gère les objets, leur cycle de
vie et leurs relations de dépendances.
    L'injection de dépendances (Dependency Injection, DI) est une implémentation de l’IoC dans
Spring. Elle consiste à fournir les dépendances (objets) d'une classe de l'extérieur plutôt que de
laisser la classe les créer elle-même. Il existe trois types d'injection de dépendances dans Spring :
       Injection par constructeur : Les dépendances sont injectées dans un objet via son
        constructeur.
       Injection par setter : Les dépendances sont injectées via des méthodes setter.
       Injection via les champs : Moins courante, cette méthode utilise directement les
        annotations sur les propriétés de la classe.
Exemple avec injection par constructeur :
       Dans cet exemple, la classe Service dépend d'une instance de Repository. Plutôt que de
la créer elle-même, Repository lui est injecté via le constructeur.
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
       Dans cet exemple, un bean Repository est défini, ainsi qu'un bean Service qui reçoit
Repository   via son constructeur.
2.2. Configuration basée sur Java (Java-based configuration)
        Avec les versions récentes de Spring, la configuration Java (ou Java-based configuration)
est devenue plus populaire, car elle est plus intuitive et permet de tirer parti des annotations et des
classes Java sans nécessiter de fichiers XML.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
     @Bean
     public Repository repository() {
         return new Repository();
     }
     @Bean
     public Service service() {
         return new Service(repository());
     }
}
        Ici, la classe AppConfig contient des méthodes annotées avec @Bean qui retournent des
instances des objets à injecter. Ces méthodes définissent les beans et leur cycle de vie.
       Lisibilité : La configuration est plus lisible et intuitive, car elle utilise directement le
        langage Java.
       Type-safe : Avec la configuration Java, vous bénéficiez des avantages de la vérification
        des types à la compilation.
       Réduction de la dépendance XML : Moins de fichiers XML à gérer et plus de contrôle
        dans le code.
3. Premier projet Spring : création d’un bean et injection de dépendances
        Pour mettre en pratique ces concepts, nous allons créer un petit projet Spring qui définit et
injecte un bean dans une classe.
Nous allons utiliser une configuration Java pour injecter Repository dans Service.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
     @Bean
     public Repository repository() {
         return new Repository();
     }
     @Bean
     public Service service() {
         return new Service(repository());
     }
}
Service en cours...
Données enregistrées !
Le Spring Framework introduit des concepts puissants comme l'Inversion of Control (IoC) et
l'injection de dépendances, qui simplifient la gestion des objets et de leurs relations dans une
application. La configuration via XML ou Java offre des approches flexibles pour déclarer les
beans, et grâce à l'injection de dépendances, les applications deviennent plus modulaires, testables
et maintenables.
      IoC et DI sont des concepts centraux dans Spring, offrant un contrôle flexible sur la création
       et la gestion des dépendances.
      Spring permet deux types principaux de configuration : XML (plus ancien) et Java-based
       configuration (plus moderne et intuitive).
      La création d’un projet Spring simple avec l’injection de dépendances permet de bien
       comprendre ces concepts.
Activité 4: Spring MVC pour le Développement Web
Objectifs de l’activité :
   L'architecture Spring MVC repose principalement sur l'utilisation de contrôleurs pour gérer
les requêtes HTTP et retourner des vues correspondantes.
2. Création d’un contrôleur Spring
         Dans Spring MVC, un contrôleur est une classe Java annotée avec @Controller qui gère
les requêtes HTTP. Chaque méthode du contrôleur peut être associée à une requête spécifique
(GET, POST, etc.) en utilisant des annotations comme @GetMapping ou @PostMapping.
         Voici un exemple de contrôleur Spring basique qui gère une requête HTTP GET et renvoie
une vue :
import   org.springframework.stereotype.Controller;
import   org.springframework.web.bind.annotation.GetMapping;
import   org.springframework.web.bind.annotation.RequestMapping;
import   org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/home")
public class HomeController {
     @GetMapping
     public ModelAndView home() {
         ModelAndView mav = new ModelAndView("home");
         mav.addObject("message", "Bienvenue dans Spring MVC !");
         return mav;
     }
}
        Les requêtes GET sont principalement utilisées pour récupérer des données. Spring MVC
utilise l'annotation @GetMapping pour définir des méthodes qui traitent ces requêtes.
Exemple d'une méthode qui gère une requête GET pour afficher un formulaire de contact :
@GetMapping("/contact")
public String showContactForm(Model model) {
    model.addAttribute("contact", new Contact());
    return "contact-form";
}
Ici, le contrôleur renvoie la vue contact-form et ajoute un objet vide Contact au modèle.
        Les requêtes POST sont utilisées pour envoyer des données, comme des informations de
formulaire. Spring MVC utilise @PostMapping pour gérer les requêtes POST.
@PostMapping("/contact")
public String submitContactForm(@ModelAttribute("contact") Contact contact, Model
model) {
    // Logique de traitement du contact (sauvegarde, validation, etc.)
    model.addAttribute("message", "Formulaire soumis avec succès !");
    return "contact-result";
}
          Spring MVC permet de combiner des objets de modèle avec des vues pour rendre des
réponses dynamiques. L’objet ModelAndView contient à la fois le modèle (les données) et la vue
(le modèle d'affichage).
          JSP (Java Server Pages) est un moteur de template couramment utilisé avec Spring MVC.
Il permet de créer des pages web dynamiques en combinant HTML et des balises JSP pour intégrer
des données Java dans la vue.
Dans cet exemple, la variable message ajoutée dans le modèle par le contrôleur est affichée dans
la vue.
          Thymeleaf est un moteur de template moderne et plus flexible que JSP. Il s'intègre
facilement à Spring MVC et permet de manipuler des modèles HTML de manière plus lisible.
Ici, l'attribut th:text remplace le contenu de l'élément avec la variable message provenant du
modèle.
        Pour utiliser Thymeleaf dans Spring, il est nécessaire de l’ajouter en tant que dépendance
dans le projet et de configurer un résolveur de vues.
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
        Voici un exemple simple d’application Spring MVC qui gère un formulaire de contact.
L’utilisateur peut soumettre ses informations, et le contrôleur les traite.
     // Getters et setters
}
5.2. Contrôleur de formulaire de contact
@Controller
@RequestMapping("/contact")
public class ContactController {
     @GetMapping
     public String showContactForm(Model model) {
         model.addAttribute("contact", new Contact());
         return "contact-form";
     }
    @PostMapping
    public String submitContactForm(@ModelAttribute("contact") Contact contact, Model
model) {
        // Traitement du formulaire (sauvegarde, validation, etc.)
        model.addAttribute("message", "Merci " + contact.getNom() + ", votre formulaire
a été soumis.");
        return "contact-result";
    }
}
    <button type="submit">Envoyer</button>
</form>
<h2>${message}</h2>
6. Conclusion
Le framework Spring MVC fournit une architecture robuste et flexible pour le développement
d’applications web. En gérant les requêtes HTTP et en intégrant des moteurs de template comme
JSP ou Thymeleaf, Spring permet de créer des applications web dynamiques et maintenables.
L'utilisation de contrôleurs et de la gestion des modèles et vues simplifie considérablement la
structuration des applications web complexes.
      Spring MVC implémente l'architecture MVC pour séparer la logique métier, l'affichage,
       et le contrôle des interactions utilisateur.
      Les contrôleurs Spring gèrent les requêtes HTTP et permettent de lier des modèles à des
       vues.
      JSP et Thymeleaf sont des moteurs de template couramment utilisés pour la création de
       vues dynamiques.
Activité 5: Bases de données avec Spring Data JPA
Objectifs de l’activité :
       Découvrir les concepts de JPA (Java Persistence API) dans le contexte de Spring.
       Apprendre à créer des entités et à les mapper aux tables d'une base de données.
       Comprendre comment utiliser Spring Data JPA pour interagir avec une base de données
        via les repositories et les query methods.
       Configurer une connexion à une base de données MySQL ou PostgreSQL.
        JPA (Java Persistence API) est une spécification Java pour la gestion des données
relationnelles dans les applications. Elle définit une manière standard d’interagir avec une base de
données à travers des objets Java appelés entités. Le but de JPA est de permettre une abstraction
du langage SQL sous-jacent, en manipulant les données directement sous forme d'objets.
        Spring utilise Hibernate, l'une des implémentations les plus populaires de JPA, pour
fournir cette couche d'abstraction.
        Spring Data JPA est un module de Spring qui simplifie l'utilisation de JPA. Il fournit une
infrastructure complète pour gérer les interactions avec les bases de données via des interfaces
appelées repositories, et offre un support pour des requêtes automatiques via des méthodes de
requête (query methods).
2. Création d'entités et mapping avec des tables de bases de données
         Une entité en JPA est une classe Java qui représente une table dans une base de données
relationnelle. Chaque instance de cette classe correspond à une ligne dans la table, et chaque attribut
de la classe est mappé à une colonne de la table.
         Les entités sont généralement annotées avec @Entity, et chaque attribut est annoté avec
@Column.    L'annotation @Id est utilisée pour désigner la clé primaire.
         Voici un exemple d’une classe Product qui représente une table products dans la base de
données :
import   javax.persistence.Entity;
import   javax.persistence.GeneratedValue;
import   javax.persistence.GenerationType;
import   javax.persistence.Id;
@Entity
public class Product {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
     // Getters et setters
}
    Cette classe sera mappée à une table product dans la base de données, avec des colonnes pour
id, name,   et price.
3. Spring Data JPA : Repositories, Query Methods
        Spring Data JPA propose un repository de base appelé CrudRepository, et un autre plus
riche appelé JpaRepository.
import org.springframework.data.jpa.repository.JpaRepository;
        Les query methods permettent d'exécuter des requêtes SQL complexes simplement en
définissant des méthodes dans les interfaces repository. Spring génère automatiquement les
requêtes en fonction du nom des méthodes.
        Ici, Spring générera automatiquement une requête qui recherche les produits en fonction de
leur nom.
Exemple d'utilisation :
        Pour des requêtes plus complexes qui ne peuvent pas être générées automatiquement, on
peut utiliser l'annotation @Query pour écrire des requêtes JPQL (Java Persistence Query Language).
Cette méthode récupérera tous les produits dont le prix est supérieur à une certaine valeur.
        Spring Boot facilite la connexion à des bases de données comme MySQL ou PostgreSQL
via le fichier application.properties ou application.yml. Il suffit de spécifier les détails de
la connexion et Spring s'occupe du reste.
        Pour se connecter à une base de données MySQL, ajoutez les informations suivantes dans
application.properties         :
spring.datasource.url=jdbc:mysql://localhost:3306/nom_de_la_base
spring.datasource.username=root
spring.datasource.password=mot_de_passe
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/nom_de_la_base
spring.datasource.username=postgres
spring.datasource.password=mot_de_passe
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
       N'oubliez pas d'ajouter la dépendance appropriée dans le fichier pom.xml de votre projet
Maven pour connecter Spring à la base de données choisie.
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
5. Exemple complet : Gestion de produits avec Spring Data JPA
        Dans cet exemple, nous allons créer une simple application qui gère une liste de produits et
les stocke dans une base de données MySQL ou PostgreSQL.
@Entity
public class Product {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
     // Getters et setters
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/products")
public class ProductController {
     @Autowired
     private ProductRepository productRepository;
     @GetMapping
     public List<Product> getAllProducts() {
         return productRepository.findAll();
     }
    @PostMapping
    public Product createProduct(@RequestBody Product product) {
        return productRepository.save(product);
    }
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productRepository.findById(id).orElseThrow(() -> new
RuntimeException("Produit non trouvé"));
    }
}
Pour MySQL :
spring.datasource.url=jdbc:mysql://localhost:3306/products_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
6. Conclusion
       L’intégration de Spring Data JPA avec JPA permet de simplifier la gestion des données
persistantes dans une application Spring. En utilisant les entités pour mapper les objets Java aux
tables de la base de données, et en manipulant les données via les repositories et les query methods,
Spring offre une solution robuste et flexible pour interagir avec les bases de données relationnelles
comme MySQL ou PostgreSQL.
Activité 6: Introduction à Spring Boot
Objectifs de l’activité :
   Spring est un framework Java complet qui offre un large éventail de fonctionnalités pour le
développement d’applications Java, notamment la gestion de la configuration, l'injection de
dépendances, et le développement d'applications web. Cependant, il nécessite souvent une
configuration manuelle et peut être complexe à mettre en place.
   Spring Boot, en revanche, est un projet dérivé de Spring qui vise à simplifier le processus de
développement en fournissant des conventions par défaut et en minimisant la configuration
nécessaire. Voici quelques différences clés :
    Pour commencer un projet Spring Boot, il est courant d'utiliser Spring Initializr, un outil en
ligne qui génère une structure de projet de base. Il permet de sélectionner les dépendances
souhaitées et de télécharger un projet prêt à être utilisé.
spring.datasource.url=jdbc:mysql://localhost:3306/nom_de_la_base
spring.datasource.username=root
spring.datasource.password=mot_de_passe
spring.jpa.hibernate.ddl-auto=update
- src
  - main
    - java
      - com
        - exemple
          - monapplication
            - MonApplication.java
            - controller
            - model
            - repository
    - resources
      - application.properties
        - static
        - templates
    - test
      - java
        - com
          - exemple
            - monapplication
@EnableAutoConfiguration, et @ComponentScan.
         Pour illustrer la création d'une application Spring Boot, nous allons développer une simple
API REST pour gérer des produits.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Double price;
      // Getters et setters
}
4.1.2. Étape 2 : Créer le repository
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/products")
public class ProductController {
     @Autowired
     private ProductRepository productRepository;
     @GetMapping
     public List<Product> getAllProducts() {
         return productRepository.findAll();
     }
     @PostMapping
     public Product createProduct(@RequestBody Product product) {
         return productRepository.save(product);
     }
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productRepository.findById(id).orElseThrow(() -> new
RuntimeException("Produit non trouvé"));
    }
}
spring.datasource.url=jdbc:mysql://localhost:3306/products_db
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
4.1.5. Étape 5: Lancer l'application
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MonApplication {
    public static void main(String[] args) {
        SpringApplication.run(MonApplication.class, args);
    }
}
        Une fois l'application lancée, vous pouvez accéder à l'API REST à l'adresse
http://localhost:8080/products.
5. Conclusion
Objectifs de l’activité :
       Comprendre le concept d'API RESTful et comment Spring Boot facilite leur création.
       Explorer l'utilisation de Spring MVC pour développer des services REST.
       Apprendre à gérer les formats de réponse, notamment JSON.
       Mettre en œuvre la validation des données d’entrée avec Bean Validation.
        Les API RESTful (Representational State Transfer) sont un ensemble de conventions pour
la création de services web qui permettent aux applications de communiquer entre elles via le
protocole HTTP. Les API RESTful utilisent des méthodes HTTP (GET, POST, PUT, DELETE)
pour effectuer des opérations sur des ressources identifiées par des URI.
       Stateless : Chaque requête du client au serveur doit contenir toutes les informations nécessaires
        pour traiter la requête.
       Identifiable par URI : Chaque ressource doit être accessible via une URI unique.
       Utilisation des méthodes HTTP : Chaque méthode HTTP correspond à une opération CRUD
        (Create, Read, Update, Delete).
        Pour créer un service REST avec Spring Boot, on utilise les annotations de Spring MVC.
Voici les étapes :
Étape 1 : Créer une entité
Prenons l’exemple de l’entité Product que nous avons déjà vue dans les activités précédentes.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
     @Autowired
     private ProductRepository productRepository;
     @GetMapping
     public List<Product> getAllProducts() {
         return productRepository.findAll();
     }
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productRepository.findById(id).orElseThrow(() -> new
RuntimeException("Produit non trouvé"));
    }
     @PostMapping
     public Product createProduct(@RequestBody Product product) {
         return productRepository.save(product);
     }
    @PutMapping("/{id}")
    public Product updateProduct(@PathVariable Long id, @RequestBody Product
productDetails) {
        Product product = productRepository.findById(id).orElseThrow(() -> new
RuntimeException("Produit non trouvé"));
        product.setName(productDetails.getName());
        product.setPrice(productDetails.getPrice());
        return productRepository.save(product);
    }
    @DeleteMapping("/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productRepository.deleteById(id);
    }
}
       Dans cet exemple, nous avons utilisé les annotations @GetMapping, @PostMapping,
@PutMapping,   et @DeleteMapping pour définir les opérations REST sur l'entité Product.
       Spring Boot supporte nativement le format JSON grâce à la bibliothèque Jackson, qui est
incluse par défaut. Cela signifie que lorsque vous retournez des objets à partir de votre contrôleur,
Spring Boot les sérialise automatiquement en JSON.
Si vous effectuez une requête GET sur /api/products, la réponse pourrait ressembler à ceci :
[
         {
              "id": 1,
              "name": "Ordinateur",
              "price": 1200.00
         },
         {
              "id": 2,
              "name": "Imprimante",
              "price": 150.00
         }
]
Configurer Jackson
         Il est possible de configurer les comportements de Jackson, comme le format des dates ou
le style de sérialisation, en ajoutant des propriétés dans application.properties :
spring.jackson.date-format=yyyy-MM-dd
spring.jackson.serialization.indent_output=true
         Bean Validation est un framework qui permet de valider les objets Java via des
annotations. Avec Spring Boot, vous pouvez facilement intégrer cette validation pour garantir que
les données entrantes sont conformes à des règles définies.
         Pour utiliser Bean Validation, vous n'avez généralement pas besoin d'ajouter des
dépendances supplémentaires, car Hibernate Validator est inclus par défaut avec Spring Boot.
Voici comment vous pouvez annoter l’entité Product pour appliquer des règles de validation :
import   javax.persistence.Entity;
import   javax.persistence.GeneratedValue;
import   javax.persistence.GenerationType;
import   javax.persistence.Id;
import   javax.validation.constraints.Min;
import   javax.validation.constraints.NotBlank;
@Entity
public class Product {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
     // Getters et setters
}
        Vous pouvez gérer les erreurs de validation dans votre contrôleur en utilisant l'objet
BindingResult      :
import org.springframework.validation.BindingResult;
@PostMapping
public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product,
BindingResult result) {
    if (result.hasErrors()) {
        // Gérer les erreurs de validation
        return ResponseEntity.badRequest().body(null);
    }
    return ResponseEntity.ok(productRepository.save(product));
}
L’annotation @Valid déclenche la validation et si des erreurs sont présentes, elles peuvent être
gérées de manière appropriée.
5. Conclusion
        Cette activité a couvert les concepts fondamentaux pour créer des API RESTful avec
Spring Boot. Vous avez appris à définir des contrôleurs REST, à gérer les réponses au format
JSON, et à appliquer des validations sur les données d'entrée via Bean Validation.
Activité 8: Sécurité avec Spring Security
Objectifs de l’activité :
2.1. Authentification
        L'authentification consiste à vérifier l'identité d'un utilisateur. Avec Spring Security, cela
se fait généralement en configurant un UserDetailsService, qui charge les détails de l'utilisateur
depuis une base de données ou un autre service.
Exemple de UserDetailsService :
import   org.springframework.beans.factory.annotation.Autowired;
import   org.springframework.security.core.userdetails.UserDetails;
import   org.springframework.security.core.userdetails.UserDetailsService;
import   org.springframework.security.core.userdetails.UsernameNotFoundException;
import   org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
     @Autowired
     private UserRepository userRepository; // Repository pour accéder aux utilisateurs
    @Override
    public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("Utilisateur non trouvé : " +
username);
        }
        return new
org.springframework.security.core.userdetails.User(user.getUsername(),
user.getPassword(), new ArrayList<>());
    }
}
2.2. Autorisation
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationMa
nagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerA
dapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("{noop}password").roles("USER")
                .and()
                .withUser("admin").password("{noop}admin").roles("ADMIN");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .httpBasic(); // Authentification de base
    }
}
       Dans cet exemple, seuls les utilisateurs avec le rôle ADMIN peuvent accéder aux routes
commençant par /api/admin, tandis que les utilisateurs avec les rôles USER et ADMIN peuvent
accéder à celles commençant par /api/user.
3.1. OAuth2
       OAuth2 est un protocole d'autorisation qui permet aux applications tierces d'accéder à des
ressources sans partager les identifiants des utilisateurs. Spring Security facilite l'intégration
d'OAuth2 pour protéger vos API.
JWT est un standard ouvert pour partager des informations de manière sécurisée entre deux parties.
Les tokens JWT peuvent être utilisés pour représenter des informations d'identité et des droits
d'accès.
3.3. Configuration de Spring Security pour utiliser OAuth2 et JWT
Pour configurer votre application Spring Boot pour utiliser OAuth2 et JWT, vous devrez ajouter
les dépendances suivantes dans votre fichier pom.xml :
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
    import   io.jsonwebtoken.Claims;
    import   io.jsonwebtoken.Jwts;
    import   io.jsonwebtoken.SignatureAlgorithm;
    import   org.springframework.stereotype.Service;
import java.util.Date;
    @Service
    public class JwtUtil {
private final String SECRET_KEY = "secret"; // Clé secrète pour signer le token
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http.csrf().disable()
                   .authorizeRequests()
                   .antMatchers("/api/auth/**").permitAll() // Autoriser l'accès aux
       endpoints d'authentification
                   .anyRequest().authenticated()
                   .and()
                   .addFilter(new JwtAuthenticationFilter(authenticationManager()));
       }
Pour mettre en place une sécurité complète dans une application Spring Boot, voici un exemple :
       import org.springframework.context.annotation.Bean;
       import org.springframework.context.annotation.Configuration;
       import
       org.springframework.security.config.annotation.authentication.builders.Authentic
       ationManagerBuilder;
       import org.springframework.security.config.annotation.web.builders.HttpSecurity;
       import
       org.springframework.security.config.annotation.web.configuration.EnableWebSecuri
   ty;
   import
   org.springframework.security.config.annotation.web.configuration.WebSecurityConf
   igurerAdapter;
   @Configuration
   @EnableWebSecurity
   public class SecurityConfig extends WebSecurityConfigurerAdapter {
       @Autowired
       private CustomUserDetailsService userDetailsService;
       @Override
       protected void configure(AuthenticationManagerBuilder auth) throws Exception
   {
           auth.userDetailsService(userDetailsService).passwordEncoder(new
   BCryptPasswordEncoder());
       }
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http.csrf().disable()
                   .authorizeRequests()
                   .antMatchers("/api/auth/**").permitAll() // Autoriser l'accès
   aux endpoints d'authentification
                   .anyRequest().authenticated()
                   .and()
                   .addFilter(new
   JwtAuthenticationFilter(authenticationManager()));
       }
   import org.springframework.security.core.Authentication;
   import org.springframework.security.core.context.SecurityContextHolder;
   import org.springframework.security.web.authentication.WebAuthenticationFilter;
   import   javax.servlet.FilterChain;
   import   javax.servlet.ServletException;
   import   javax.servlet.http.HttpServletRequest;
   import   javax.servlet.http.HttpServletResponse;
   import   java.io.IOException;
       @Override
       protected void doFilterInternal(HttpServletRequest request,
   HttpServletResponse response, FilterChain chain)
               throws ServletException, IOException {
                String token = request.getHeader("Authorization");
                chain.doFilter(request, response);
            }
       }
5. Conclusion
Cette activité a couvert les bases de la sécurité des applications Spring avec Spring Security. Vous
avez appris à gérer l'authentification et l'autorisation, à intégrer OAuth2 et JWT, et à mettre en
place une configuration de sécurité dans une application Spring Boot.
Activité 9: Transactions et Gestion des Transactions avec Spring
Objectifs de l’activité :
Les transactions sont des unités de travail qui doivent être exécutées de manière atomique. Le
modèle ACID définit les propriétés essentielles qu'une transaction doit respecter pour garantir
l'intégrité des données :
      Atomicité : Une transaction est atomique, ce qui signifie qu'elle est soit entièrement
       exécutée, soit pas du tout. Si une partie de la transaction échoue, tous les changements
       effectués sont annulés.
      Cohérence : Les transactions doivent amener la base de données d'un état valide à un autre
       état valide. Cela garantit que toutes les contraintes de la base de données sont respectées
       avant et après la transaction.
      Isolation : Les transactions concurrentes doivent être isolées les unes des autres. Les
       modifications apportées par une transaction ne doivent pas être visibles par d'autres
       transactions tant qu'elles ne sont pas validées.
      Durabilité : Une fois qu'une transaction est validée, ses modifications sont permanentes,
       même en cas de défaillance du système.
Cette approche utilise les annotations ou XML pour définir les transactions. Spring gère
automatiquement les transactions en fonction de la configuration.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ProductService {
     @Autowired
     private ProductRepository productRepository;
     @Transactional
     public void createProduct(Product product) {
         productRepository.save(product);
         // D'autres opérations peuvent être ajoutées ici
     }
}
Dans cet exemple, la méthode createProduct est annotée avec @Transactional. Cela signifie
que Spring gérera automatiquement la transaction pour cette méthode.
Cette approche permet aux développeurs de gérer manuellement les transactions. Cela offre plus
de contrôle, mais cela nécessite également plus de code.
import   org.springframework.beans.factory.annotation.Autowired;
import   org.springframework.stereotype.Service;
import   org.springframework.transaction.PlatformTransactionManager;
import   org.springframework.transaction.TransactionStatus;
import   org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class ProductService {
     @Autowired
     private ProductRepository productRepository;
      @Autowired
      private PlatformTransactionManager transactionManager;
Dans cet exemple, nous avons utilisé PlatformTransactionManager pour gérer manuellement la
transaction.
Spring intègre parfaitement JPA pour la gestion des transactions. Lorsque vous utilisez
@Transactional,     Spring gère les transactions en fonction de la configuration de JPA.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class OrderService {
      @Autowired
      private OrderRepository orderRepository;
      @Transactional
      public void placeOrder(Order order) {
          orderRepository.save(order);
          // D'autres opérations, comme mettre à jour le stock, peuvent être effectuées
ici
     }
     @Transactional(readOnly = true)
     public List<Order> getAllOrders() {
         return orderRepository.findAll();
     }
}
Dans cet exemple, nous avons une méthode placeOrder qui enregistre une commande et une
méthode getAllOrders qui récupère toutes les commandes sans modifier l'état de la base de
données.
4. Exemples pratiques
Imaginons une méthode qui effectue une opération de transfert d'argent entre deux comptes
bancaires. Cela nécessite que deux opérations soient effectuées avec succès ou que les deux soient
annulées.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BankService {
     @Autowired
     private AccountRepository accountRepository;
    @Transactional
    public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
        Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow(()
-> new RuntimeException("Compte non trouvé"));
        Account toAccount = accountRepository.findById(toAccountId).orElseThrow(() ->
new RuntimeException("Compte non trouvé"));
           fromAccount.setBalance(fromAccount.getBalance() - amount);
           toAccount.setBalance(toAccount.getBalance() + amount);
           accountRepository.save(fromAccount);
           accountRepository.save(toAccount);
     }
}
Exemple 2 : Gestion des transactions avec des erreurs
Lorsque vous traitez des opérations qui peuvent échouer, il est essentiel de gérer les exceptions
pour annuler la transaction.
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PaymentService {
     @Autowired
     private PaymentRepository paymentRepository;
     @Autowired
     private OrderRepository orderRepository;
     @Transactional
     public void processPayment(Payment payment) {
         orderRepository.findById(payment.getOrderId())
                 .orElseThrow(() -> new RuntimeException("Commande non trouvée"));
Dans cet exemple, si le traitement du paiement échoue, la transaction sera annulée et toutes les
modifications précédentes seront également annulées.
5. Conclusion
Cette activité a exploré la gestion des transactions dans Spring, y compris les concepts ACID, les
approches déclaratives et programmatiques de gestion des transactions, et l'intégration de JPA.
Vous avez également examiné des exemples pratiques pour mieux comprendre comment gérer
efficacement les transactions dans une application Spring Boot.
Activité 10: Messaging et Intégration avec JMS et RabbitMQ
Objectifs de l’activité :
Java Messaging Service (JMS) est une API Java qui permet à des applications Java de
communiquer entre elles en utilisant des messages. JMS permet une communication asynchrone,
ce qui signifie que les expéditeurs et les récepteurs de messages peuvent fonctionner
indépendamment les uns des autres.
       Asynchrone : Les messages peuvent être envoyés et reçus à des moments différents.
       Découplage : Les producteurs et les consommateurs de messages ne doivent pas être en ligne en
        même temps.
       Fiabilité : JMS garantit la livraison des messages et peut gérer les pannes de manière efficace.
       Queue (file d'attente) : Utilisé pour une communication point à point. Un message est consommé
        par un seul consommateur.
       Topic (sujet) : Utilisé pour une communication de publication/abonnement. Un message est diffusé
        à tous les abonnés.
2. Utilisation de RabbitMQ avec Spring Boot
Pour commencer, vous devez ajouter les dépendances RabbitMQ à votre projet. Voici un exemple
de configuration avec Maven :
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
Pour envoyer des messages à RabbitMQ, nous pouvons utiliser la classe RabbitTemplate.
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
     @Autowired
     private RabbitTemplate rabbitTemplate;
Pour recevoir des messages, nous devons créer un MessageListener qui écoutera les messages
arrivant sur la queue.
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MessageListener {
     @RabbitListener(queues = "myQueue")
     public void receiveMessage(String message) {
         System.out.println("Message reçu : " + message);
     }
}
Imaginons une application qui envoie un message chaque fois qu'un utilisateur s'inscrit.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Autowired
    private MessageProducer messageProducer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class OrderProcessingService {
    @RabbitListener(queues = "orderQueue")
    public void processOrder(Order order) {
        // Logique de traitement de commande
        System.out.println("Traitement de la commande : " + order.getId());
        // ...
    }
}
5. Conclusion
Cette activité a exploré les concepts fondamentaux de Java Messaging Service (JMS) et comment
utiliser RabbitMQ avec Spring Boot pour gérer des messages asynchrones. Vous avez appris à
envoyer et recevoir des messages et à intégrer RabbitMQ dans vos applications Spring.
Activité 11: Tests et Déploiement des Applications Spring Boot
Objectifs de l’activité :
Les tests sont essentiels pour garantir que les applications fonctionnent comme prévu. Dans Spring
Boot, deux types de tests sont couramment utilisés :
       Tests unitaires : Vérifient des unités de code isolées (par exemple, des méthodes individuelles)
        pour s'assurer qu'elles se comportent comme prévu.
       Tests d'intégration : Vérifient que différentes parties de l'application fonctionnent correctement
        ensemble.
JUnit est un cadre de test populaire pour Java, tandis que Mockito est une bibliothèque de
simulation qui permet de créer des objets fictifs (mock objects) pour les tests unitaires.
2.1. JUnit
Pour ajouter JUnit à votre projet, vous pouvez utiliser la dépendance suivante dans votre fichier
pom.xml      :
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.8.1</version>
    <scope>test</scope>
</dependency>
     @Test
     public void testAddition() {
         Calculator calculator = new Calculator();
         assertEquals(5, calculator.add(2, 3));
     }
}
2.2. Mockito
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.12.4</version>
    <scope>test</scope>
</dependency>
     @Test
     public void testGetUser() {
         UserRepository userRepository = mock(UserRepository.class);
         UserService userService = new UserService(userRepository);
         User user = new User("John");
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
          assertEquals("John", userService.getUser(1L).getName());
     }
}
Spring Boot fournit des annotations pour faciliter les tests des contrôleurs et des services.
import   org.junit.jupiter.api.Test;
import   org.springframework.beans.factory.annotation.Autowired;
import   org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import   org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(UserController.class)
public class UserControllerTest {
     @Autowired
     private MockMvc mockMvc;
     @Test
     public void testGetUser() throws Exception {
         mockMvc.perform(get("/users/1"))
                 .andExpect(status().isOk())
                 .andExpect(content().string("User details for id: 1"));
     }
}
3.2. Tests de services
Utilisez l’annotation @SpringBootTest pour tester les services avec toute l'application chargée.
@SpringBootTest
public class UserServiceIntegrationTest {
     @Autowired
     private UserService userService;
     @Test
     public void testGetAllUsers() {
         assertEquals(3, userService.getAllUsers().size());
     }
}
Le déploiement d’une application Spring Boot peut être réalisé sur plusieurs plateformes. Voici un
aperçu des étapes de déploiement sur Heroku, AWS, et OVH.
java.runtime.version=17
    4. Déployer l’application :
       heroku create your-app-name
       git push heroku main
5. Conclusion
Cette activité a couvert les tests unitaires et d’intégration dans une application Spring Boot à l'aide
de JUnit et Mockito, ainsi que le test des couches web et de services. Vous avez également exploré
le déploiement d'applications Spring Boot sur des plateformes comme Heroku, AWS et OVH.
Cette dernière activité conclut notre cours sur le développement avec Java EE, Spring et Spring
Boot. Vous êtes désormais équipés pour développer, tester et déployer des applications robustes et
évolutives.
Activité 12: Projet Final
Objectifs de l’activité :
1. Conception de l'application
Les étudiants doivent choisir un sujet d'application qui les intéresse. Quelques idées peuvent inclure
:
Les étudiants doivent définir une architecture pour leur application, en considérant :
Créer un projet Spring Boot à l'aide de Spring Initializr, en incluant les dépendances nécessaires :
       API REST : Créer des endpoints pour gérer les opérations CRUD (Create, Read, Update, Delete).
       Accès aux données : Utiliser Spring Data JPA pour interagir avec la base de données.
       Gestion de la sécurité : Implémenter l'authentification des utilisateurs à l'aide de Spring Security
        (par exemple, en utilisant JWT).
       Gestion des transactions : S'assurer que les opérations critiques sont gérées transactionnellement.
@RestController
@RequestMapping("/api/books")
public class BookController {
    @Autowired
    private BookService bookService;
    @GetMapping
    public List<Book> getAllBooks() {
        return bookService.findAll();
    }
    @PostMapping
    public Book createBook(@RequestBody Book book) {
        return bookService.save(book);
    }
}
3. Déploiement de l'application
Les étudiants peuvent choisir une des plateformes suivantes pour déployer leur application :
4. Présentation du projet
Les étudiants doivent préparer une présentation de leur projet qui inclut :
       Vue d'ensemble de l'application : Expliquer le problème résolu par l'application et son public
        cible.
       Démo en direct : Montrer les fonctionnalités de l'application.
       Techniques utilisées : Discuter des technologies et des concepts Spring appliqués.
       Défis rencontrés : Partager les obstacles et les solutions trouvées pendant le développement.
       Leçons apprises : Réfléchir sur ce qu'ils ont appris tout au long du processus.
4.2. Feedback
5. Conclusion
Cette activité finale permet aux étudiants de synthétiser tout ce qu'ils ont appris pendant le cours et
d'appliquer ces connaissances dans un projet concret. En intégrant Spring Boot, Spring Data JPA,
Spring Security, et d'autres concepts, les étudiants auront l'opportunité de démontrer leurs
compétences et leur compréhension du développement d'applications Java modernes. Cela
constitue également une excellente expérience pour leur future carrière dans le développement
logiciel.