Illustration du tutoriel Apache Kafka 3/6 avec les logos GitLab CI, Spring Boot, Kafka et Docker sur fond bleu, dédié au développement backend Java

Construire un backend Spring Boot structuré : modèle, repository et configuration Kafka (3/6)

Bienvenue dans la troisième partie de notre série de tutoriels sur l’intégration d’Apache Kafka dans une application moderne ! Dans la première partie, nous avons exploré l’architecture globale de notre application de messagerie sociale et posé les bases conceptuelles du projet. Puis, la deuxième partie nous a permis de mettre en place notre environnement de développement avec Docker Compose, en configurant notamment MySQL et Kafka. Il est maintenant temps de construire le cœur de notre application : le backend.

Cette section vous guidera dans la création du backend. Ce dernier sera en Java, utilisant Spring Boot 3.4.7. Il exposera une API REST pour gérer les messages. Son objectif principal est de concevoir une application moderne. Elle sera connectée à MySQL et également préparée pour publier des événements sur Kafka. Pour démarrer ce processus, nous allons générer un projet via l’outil officiel Spring Initializr. Ensuite, nous l’intégrerons à l’architecture globale de notre projet.

💡 Code source complet de l’exercice

Vous pouvez consulter et cloner le code source correspondant à ce tutoriel sur GitLab :
👉 gitlab.com/springboot-kafka-social-lab
Ce tag v1.0.0 correspond à la version réalisée dans ce tutoriel.
Le projet continuera à évoluer, donc vous pouvez aussi consulter la branche main ou develop pour suivre les mises à jour ultérieures.

1. Génération du projet avec Spring Initializr.

Accédez à start.spring.io. Configurez ensuite les options suivantes pour votre projet :

  • Project : Gradle – Groovy DSL
  • Language : Java
  • Spring Boot : 3.4.7
  • Java : 17 ou plus. Spring Boot 3.x requiert Java 17 au minimum. Les versions récentes, telles que Java 21 (choix utilisé dans ce tutoriel) ou même Java 23, sont également compatibles.
  • Packaging : Jar
  • Group : com.izonova
  • Artifact : sociallab
  • Name : sociallab-backend

Cliquez ensuite sur “Generate”. Cela téléchargera l’archive ZIP du projet sur votre machine.

1.1. Dépendances à inclure

Lors de la génération du projet, sélectionnez les dépendances suivantes, car elles sont indispensables :

Spring Web

Cette dépendance est essentielle. Elle sert à créer une API REST. Grâce à elle, vous exposez des endpoints HTTP. Par conséquent, elle constitue le cœur de la communication entre le frontend et le backend. Elle est donc fondamentale.

Spring Data JPA

Spring Data JPA facilite grandement l’interaction avec la base de données. Il utilise des entités Java et des interfaces Repository. Grâce à cela, vous n’avez pas besoin d’écrire de code SQL. C’est un gain de temps considérable.

Spring for Apache Kafka

Cette dépendance simplifie l’intégration de Kafka. En effet, grâce à elle, le backend pourra produire (et plus tard consommer) des messages Kafka. Il est important de noter que l’implémentation de la logique Kafka sera détaillée dans la partie suivante de ce tutoriel.

MySQL Driver

Le pilote MySQL ajoute le connecteur JDBC nécessaire. Ainsi, Spring peut se connecter à une base MySQL sans problème. Il est donc indispensable.

🛠️ Spring Boot DevTools (facultatif mais recommandé)

Cet outil améliore significativement l’expérience de développement local. Il offre des fonctionnalités très utiles, telles que le rechargement automatique du code ou la désactivation du cache. Par conséquent, son utilisation est vivement conseillée.

🧩 Lombok (facultatif mais très utile)

Lombok est un outil puissant. Il supprime le code répétitif. En effet, il génère automatiquement les getters, setters ou constructeurs via des annotations. Par exemple, utilisez @Data, @Builder ou @NoArgsConstructor pour simplifier votre code. C’est un atout majeur pour la propreté du code.

1.2. Structure du projet généré

Une fois le projet généré et extrait, vous obtiendrez la structure suivante :

sociallab-backend/
├── build.gradle # Fichier de configuration Gradle
├── settings.gradle # Nom du projet
├── gradlew # Wrapper Gradle (Linux/macOS)
├── gradlew.bat # Wrapper Gradle (Windows)
├── gradle/ # Fichiers liés au wrapper
└── src/
└── main/
├── java/com/izonova/sociallab/ # Code source Java
└── resources/ # Fichiers de configuration (application.properties, etc.)

📌 Grâce au wrapper (gradlew), vous pouvez exécuter des commandes Gradle. Cela se fait sans avoir à installer Gradle sur votre machine, ce qui est très pratique pour la portabilité du projet.

1.3. Intégration dans l’architecture globale du projet

Notre projet est structuré pour accueillir plusieurs composants distincts. Par exemple, nous avons le backend et le frontend. Copiez tout le contenu de l’archive générée. Placez-le dans le dossier backend/ de votre projet principal. Cela assure une bonne organisation des fichiers.

springboot-kafka-social-lab/
├── backend/ # Code source du backend Spring Boot
│ ├── build.gradle
│ ├── settings.gradle
│ ├── gradlew
│ ├── gradlew.bat
│ ├── gradle/
│ └── src/
├── frontend/ # Interface utilisateur Vue.js
├── docker-compose.yml # Orchestration des services
└── README.md

✅ Cette organisation claire permet de séparer proprement le backend du reste de l’application. Elle simplifie aussi la collaboration entre développeurs. De plus, elle facilite le déploiement multi-conteneurs via Docker. C’est un atout majeur pour les projets complexes.

2. Mise en place de la structure du backend.

Maintenant, notre projet Spring Boot est généré et intégré dans le dossier backend. Nous allons créer les différentes classes qui constituent l’architecture logique du backend. Cela est essentiel pour la suite du développement.

Pour rester lisible et maintenable, notre application est organisée selon des packages métier clairement identifiés. Voici leur rôle :

PackageRôle
modelDéfinit les entités de données (JPA)
repositoryFournit l’accès à la base via Spring Data
serviceContient la logique métier de base (sera enrichi en partie suivante)
kafkaGère la production et consommation de messages Kafka (détaillé dans la partie suivante)
controllerExpose les endpoints de l’API REST
confRegroupe les configurations techniques (CORS, Kafka, etc.)

Nous allons les construire progressivement, dans l’ordre suivant :

  1. Le modèle de données (model) et l’accès aux données (repository).
  2. Le contrôleur REST (controller) et la configuration technique (conf).

2.1. Entité Message (package model)

La classe Message représente un message utilisateur. Ce message est publié dans l’application. Il sera stocké dans la base MySQL. Par ailleurs, il sera diffusé via Kafka.

📄 Fichier : src/main/java/com/izonova/sociallab/model/Message.java

package com.izonova.sociallab.model;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

/**
 * Entity representing a message in the social app.
 */
@Getter
@Entity
@Table(name = "messages")
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Setter
    @Column(nullable = false)
    private String content;

    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;

    public Message() {
        // Required by JPA
    }

    public Message(String content) {
        this.content = content;
    }

    @PrePersist
    public void prePersist() {
        this.createdAt = LocalDateTime.now();
    }
}

💡 Explication
  • @Entity : Cette annotation indique que la classe est une entité JPA. En d’autres termes, elle représente une table dans la base de données.
  • @Table(name = "messages") : Elle précise le nom exact de la table associée dans la base de données. Ici, c’est « messages ».
  • @Id + @GeneratedValue : Ces annotations définissent la clé primaire de l’entité. De plus, elle sera auto-incrémentée par la base de données.
  • Le champ createdAt est fixé automatiquement. Cela se produit juste avant l’insertion en base, via la méthode annotée @PrePersist. Ainsi, la date de création est toujours enregistrée.
  • Lombok est utilisé pour générer les getters. Il ne génère que le setter de content. Cela réduit le code « boilerplate ».

2.2. Interface MessageRepository (package repository)

Spring Data JPA permet d’accéder à la base de données sans écrire de code SQL. Pour ce faire, il suffit d’étendre JpaRepository. Cela simplifie grandement les opérations d’accès aux données. C’est une fonctionnalité très puissante.

📄 Fichier : src/main/java/com/izonova/sociallab/repository/MessageRepository.java

package com.izonova.sociallab.repository;

import com.izonova.sociallab.model.Message;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * Repository interface for accessing messages from the database.
 */
@Repository
public interface MessageRepository extends JpaRepository<Message, Long> {
    // Basic CRUD methods are provided automatically
}

💡 Explication
  • Cette interface gère l’accès à la table messages. C’est sa fonction principale.
  • Toutes les méthodes classiques (comme save, findAll ou deleteById) sont déjà disponibles. De ce fait, vous n’avez pas à les implémenter.
  • L’annotation @Repository est optionnelle. Cependant, elle améliore la lisibilité. Elle facilite également la gestion des exceptions spécifiques à la persistance.

2.3. Service métier MessageService (package service)

Le service MessageService est le composant central de notre logique métier. Dans cette version initiale, il se concentre sur la gestion des messages et leur persistance en base de données. L’intégration de Kafka viendra dans une étape ultérieure.

📄 Fichier : src/main/java/com/izonova/sociallab/service/MessageService.java

package com.izonova.sociallab.service;

import com.izonova.sociallab.model.Message;
import com.izonova.sociallab.repository.MessageRepository;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Service layer handling message persistence.
 * (Initial version without Kafka integration)
 */
@Service
public class MessageService {

    private final MessageRepository messageRepository;

    public MessageService(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }

    /**
     * Returns all messages from the database.
     */
    public List<Message> getAllMessages() {
        return messageRepository.findAll();
    }

    /**
     * Saves a new message to the database.
     */
    public Message saveMessage(Message message) {
        return messageRepository.save(message);
    }
}

💡 Explication
  • Ce service injecte uniquement le MessageRepository. Il l’utilise pour interagir avec la base de données.
  • La méthode saveMessage() se charge de sauvegarder un nouveau message dans MySQL.
  • La méthode getAllMessages() permet de récupérer tous les messages déjà persistés.
  • Il est important de noter que cette version ne gère pas encore l’envoi de messages vers Kafka. Cette fonctionnalité sera ajoutée lors de la Partie 4.

2.4. Contrôleur REST MessageController (package controller)

Le contrôleur MessageController expose deux endpoints HTTP principaux. Ils permettent d’interagir avec le backend :

  1. Récupérer tous les messages
  2. Poster un nouveau message

📄 Fichier : src/main/java/com/izonova/sociallab/controller/MessageController.java

package com.izonova.sociallab.controller;

import com.izonova.sociallab.model.Message;
import com.izonova.sociallab.service.MessageService; // Using the initial version from this part
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * REST controller exposing endpoints to interact with messages.
 */
@RestController
@RequestMapping("/api/messages")
@CrossOrigin(origins = "*")
public class MessageController {

    private final MessageService messageService;

    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    /**
     * GET /api/messages : returns all messages.
     */
    @GetMapping
    public List<Message> getMessages() {
        return messageService.getAllMessages();
    }

    /**
     * POST /api/messages : creates a new message.
     */
    @PostMapping
    public Message postMessage(@RequestBody Message message) {
        return messageService.saveMessage(message);
    }
}

💡 Explication
  • @RestController : Cette annotation indique que la classe gère les requêtes REST. En conséquence, Spring la traite comme un contrôleur d’API.
  • @RequestMapping("/api/messages") : Elle définit la racine commune pour tous les endpoints de ce contrôleur. Cela simplifie l’organisation des URLs.
  • @GetMapping : Cette annotation permet de retourner tous les messages. C’est une opération de lecture, accessible via une requête GET.
  • @PostMapping : Elle est utilisée pour publier un nouveau message. Il s’agit d’une opération d’écriture, accessible via une requête POST.
  • @CrossOrigin(origins = "*") : Cette annotation autorise les appels depuis n’importe quelle origine (CORS). C’est très utile en phase de développement.

Ce contrôleur constitue le point d’entrée unique du frontend vers le backend. Il est important de noter qu’il utilise ici la version initiale du MessageService que nous venons de définir. Le MessageService sera enrichi avec l’intégration Kafka dans la Partie 4 du tutoriel.

2.5. Configuration Web WebConfig (package conf)

Spring Boot active une configuration CORS minimale par défaut. Cependant, pour personnaliser cela ou centraliser d’autres réglages, on peut créer une classe de configuration dédiée. Cette approche est plus structurée et flexible.

📄 Fichier : src/main/java/com/izonova/sociallab/conf/WebConfig.java

package com.izonova.sociallab.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Global web configuration (CORS, etc.).
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // Allow all endpoints
                .allowedOrigins("*") // Accept requests from any domain
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");
    }
}

💡 Explication
  • La classe implémente WebMvcConfigurer. Elle sert à personnaliser la configuration web globale de l’application.
  • Ici, toutes les origines (*) sont autorisées. De plus, les méthodes HTTP courantes (GET, POST, PUT, DELETE, OPTIONS) sont également permises.
  • Ce type de configuration est très utile. En effet, il aide à éviter les erreurs CORS côté navigateur. C’est surtout vrai lors du développement local ou avec un frontend séparé (Vue.js, React…).

Conclusion

Dans cette troisième partie, vous avez posé les fondations de notre backend Spring Boot. Vous avez appris à générer un projet et à organiser sa structure. Vous avez aussi créé les entités de données. Vous maîtrisez également l’accès à la base de données et l’exposition d’une API REST fonctionnelle. C’est un pas majeur dans la construction de notre application moderne.

La suite dans la Partie 4

Le prochain article sera crucial. Nous y implémenterons la logique métier de notre service. Surtout, nous intégrerons Apache Kafka en détail. Nous verrons comment produire et consommer des messages. Cela connectera ainsi notre backend au système de messagerie asynchrone. Préparez-vous à l’étape suivante de notre projet fullstack !

Pour rappel, la Partie 1 de ce tutoriel a exploré l’architecture de l’application et les prérequis. La Partie 2 a couvert la mise en place de l’environnement Dockerisé pour MySQL et Kafka, un prérequis indispensable.

💬 Une question ou une remarque ?

Nous vous encourageons à poser vos questions en commentaire. Toute remarque ou suggestion est également la bienvenue !

Logo de Izo-Nova

Rejoignez-nous !

Recevez une sélection de nos meilleurs articles, guides d'achat et analyses. L'essentiel de la tech, directement dans votre boîte mail.

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest

0 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
Retour en haut