Spring Boot : API REST
Pourquoi Spring Boot : API REST ?
Dans un monde où les applications sont de plus en plus connectées et partagent des données entre elles, les API (Application Programming Interfaces) jouent un rôle crucial. Les API permettent aux différents systèmes d'interagir entre eux, échanger des informations et effectuer des opérations sur ces données. L'API REST est l'une de ces interfaces, utilisée pour créer des applications web qui communiquent via le protocole HTTP.
Un cas d'usage concret serait le développement d'un service de gestion des tâches. A chaque utilisateur, on souhaite pouvoir ajouter, modifier et supprimer des tâches. L'API REST permet de créer des endpoints pour ces opérations, chacun correspondant à une requête HTTP différente (GET pour récupérer, POST pour ajouter, PUT pour modifier et DELETE pour supprimer).
Prerequis
Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :
- Connaissance de base de Java
- Installation d'Java JDK 17 ou ultérieur
- IDE comme IntelliJ IDEA ou Eclipse
- Apache Maven 3.5 ou ultérieur
- Terminal pour exécuter des commandes
Concepts fondamentaux
1. Projet Spring Boot
Spring Boot est un framework Java qui facilite la création de applications web et les services basés sur le modèle MVC (Model-View-Controller). Il utilise l'annotation @SpringBootApplication pour démarrer une application.
// Importations nécessaires
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // Marque cette classe comme la classe principale de l'application Spring Boot
public class ApiRestApplication {
public static void main(String[] args) {
SpringApplication.run(ApiRestApplication.class, args); // Démarrage de l'application
}
}
2. Contrôleurs (Controllers)
Les contrôleurs gèrent les requêtes HTTP et génèrent les réponses. Ils sont annotés avec @RestController pour indiquer qu'ils traitent des demandes REST.
// Importations nécessaires
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // Marque cette classe comme un contrôleur de REST
@RequestMapping("/api/tasks") // Spécifie le chemin base pour toutes les méthodes de ce contrôleur
public class TaskController {
@GetMapping("/") // Mappe la méthode à une requête GET sur /api/tasks/
public String getAllTasks() {
return "Liste des tâches";
}
}
3. Services (Services)
Les services contiennent la logique métier de l'application. Ils sont appelés par les contrôleurs.
// Importations nécessaires
import org.springframework.stereotype.Service;
@Service // Marque cette classe comme un service Spring
public class TaskService {
public String getAllTasks() {
return "Liste des tâches depuis le service";
}
}
4. Modèles (Models)
Les modèles représentent les données de l'application. Ils sont souvent basés sur les entités JPA.
// Importations nécessaires
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity // Marque cette classe comme une entité JPA
public class Task {
@Id // Indique que ce champ est la clé primaire
@GeneratedValue(strategy = GenerationType.IDENTITY) // Génère automatiquement les ID
private Long id;
private String description;
// Getters et Setters
}
Mise en pratique : projet fil rouge
Étape 1 : Créer un nouveau projet Spring Boot
- Ouvrez votre IDE (IntelliJ IDEA ou Eclipse) et créez un nouveau projet Spring Boot.
- Sélectionnez le template "Spring Initializr" et configurez-le comme suit :
- Project: Maven Project
- Language: Java
- Spring Boot: 3.0.x (ou ultérieur)
- Packaging: Jar
- Java: 17
- Ajoutez les dépendances suivantes : Spring Web, Spring Data JPA, H2 Database
Étape 2 : Configurer la base de données
Ajoutez les configurations pour la base de données H2 dans le fichier application.properties.
## application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
Étape 3 : Créer le modèle
Créez un fichier Task.java dans le package com.example.demo.model.
// Task.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Étape 4 : Créer le repository
Créez un fichier TaskRepository.java dans le package com.example.demo.repository.
// TaskRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
public interface TaskRepository extends JpaRepository<Task, Long> {
}
Étape 5 : Créer le service
Créez un fichier TaskService.java dans le package com.example.demo.service.
// TaskService.java
import com.example.demo.model.Task;
import com.example.demo.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskService {
@Autowired
private TaskRepository taskRepository;
public List<Task> getAllTasks() {
return taskRepository.findAll();
}
public Task addTask(Task task) {
return taskRepository.save(task);
}
}
Étape 6 : Créer le contrôleur
Créez un fichier TaskController.java dans le package com.example.demo.controller.
// TaskController.java
import com.example.demo.model.Task;
import com.example.demo.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/tasks")
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/")
public List<Task> getAllTasks() {
return taskService.getAllTasks();
}
@PostMapping("/")
public Task addTask(@RequestBody Task task) {
return taskService.addTask(task);
}
}
Étape 7 : Tester l'API
- Lancez l'application en exécutant la classe
ApiRestApplication. - Ouvrez un navigateur et accédez à
http://localhost:8080/api/tasks/. Vous devriez voir une liste vide. - Accédez à
http://localhost:8080/h2-console/pour vous connecter à la base de données H2 et ajouter des tâches.
Erreurs frequentes et debugging
1. Erreur : could not resolve placeholder 'spring.datasource.url'
## Message d'erreur exact
Description: Failed to start bean 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException:
Failed to instantiate [org.springframework.boot.jdbc.DataSourceBuilder]: Factory method 'dataSource' threw exception;
nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.url' in value "${spring.datasource.url}"
Code incorrect :
## application.properties
spring.datasource.url=
Code correct :
## application.properties
spring.datasource.url=jdbc:h2:mem:testdb
2. Erreur : NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.repository.TaskRepository' available
## Message d'erreur exact
Description: Failed to instantiate [com.example.demo.service.TaskService]: Factory method 'taskService' threw exception;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.example.demo.repository.TaskRepository' available
Code incorrect :
// TaskService.java
import com.example.demo.model.Task;
@Service
public class TaskService {
public List<Task> getAllTasks() {
return taskRepository.findAll(); // taskRepository non déclaré
}
}
Code correct :
// TaskService.java
import com.example.demo.model.Task;
import com.example.demo.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskService {
@Autowired
private TaskRepository taskRepository; // Injection du repository
public List<Task> getAllTasks() {
return taskRepository.findAll();
}
}
3. Erreur : Could not start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
## Message d'erreur exact
Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Code incorrect :
## application.properties
spring.datasource.username=sa
spring.datasource.password=
Code correct :
## application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
Pour aller plus loin
1. Sécurité avec Spring Security
L'ajout de la sécurité est crucial pour les applications RESTful. Spring Security peut être utilisé pour protéger les endpoints.
2. Validation des données
Pour s'assurer que les données entrées sont valides, vous pouvez utiliser les annotations de validation de Java Bean (JSR-380).
3. Gestion des exceptions
La gestion des exceptions est essentielle pour une application robuste. Vous pouvez créer des classes de gestion d'exceptions personnalisées.
Défi pratique
Développez un endpoint GET /api/tasks/{id} pour récupérer une tâche spécifique par son ID. Assurez-vous de gérer les cas où la tâche n'est pas trouvée.
// TaskController.java
@GetMapping("/{id}")
public ResponseEntity<Task> getTaskById(@PathVariable Long id) {
Optional<Task> task = taskService.findById(id);
if (task.isPresent()) {
return ResponseEntity.ok(task.get());
} else {
return ResponseEntity.notFound().build();
}
}
Ce tutoriel vous a permis de créer une API REST complète en utilisant Spring Boot. Vous avez appris les concepts fondamentaux, mis en pratique la création d'un projet réel et résolu quelques erreurs courantes. Pour aller plus loin, vous pouvez explorer des fonctionnalités avancées comme la sécurité et la gestion des exceptions.