Guide des Annotations
Guide complet des annotations Lombok et Micronaut utilisées dans l’architecture hexagonale.
Ce guide explique toutes les annotations utilisées dans le projet avec des exemples concrets et du code généré automatiquement.
Pourquoi ce guide ?
Comprendre ces annotations est essentiel pour :
- Réduire le boilerplate : Lombok génère automatiquement getters, setters, constructeurs…
- Maîtriser l’injection de dépendances : Micronaut gère les dépendances avec @Singleton
- Créer des APIs REST : Controllers et mapping HTTP simplifiés
- Écrire du code propre : Moins de code = plus de lisibilité
Annotations Lombok
Lombok génère du code automatiquement pour éviter le boilerplate. Toutes ces annotations fonctionnent à la compilation.
@RequiredArgsConstructor
Crée un constructeur avec tous les champs final ou @NonNull.
Code avec Lombok
@RequiredArgsConstructor
public class GetTrendsUseCase {
private final TrendRepository trendRepository;
private final Logger logger;
}Quand l’utiliser : Pour l’injection de dépendances dans vos use cases, controllers, repositories.
@AllArgsConstructor
Crée un constructeur avec TOUS les champs (pas seulement les final).
Code avec Lombok
@AllArgsConstructor
public class User {
private String name;
private int age;
private String email;
}Moins utilisé que @RequiredArgsConstructor. Préférez @Value pour les classes immutables.
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
Modifie automatiquement les modificateurs de tous les champs de la classe.
Options :
level = AccessLevel.PRIVATE→ Tous les champs deviennentprivatemakeFinal = true→ Tous les champs deviennentfinal
Avec @FieldDefaults
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TrendController {
GetTrendsUseCase getTrendsUseCase;
}Évite de répéter private final devant chaque champ. Parfait en combinaison avec @RequiredArgsConstructor.
@Value
Crée une classe immutable (non modifiable) en une seule annotation.
Équivalent à :
@AllArgsConstructor@Getter(tous les champs)@FieldDefaults(level = PRIVATE, makeFinal = true)@ToString@EqualsAndHashCode
Avec @Value
@Value
public class TrendQuery {
String keyword;
String region;
LocalDateTime timestamp;
}Idéal pour :
- DTOs (Data Transfer Objects)
- Entités du domain
- Value Objects
- Toute classe qui ne doit jamais changer une fois créée
Annotations Micronaut
Micronaut gère l’injection de dépendances et le cycle de vie des beans avec ces annotations.
@Singleton
Dit à Micronaut de créer une seule instance de cette classe et de la réutiliser partout.
@Singleton
public class GetTrendsUseCase {
// Une seule instance partagée dans toute l'application
}Comportement :
GetTrendsUseCase instance1 = context.getBean(GetTrendsUseCase.class);
GetTrendsUseCase instance2 = context.getBean(GetTrendsUseCase.class);
// instance1 == instance2 → TRUE (même objet réutilisé!)Quand l’utiliser :
- Use cases
- Services métier
- Repositories
- Tout ce qui n’a pas d’état mutable (pas de champs modifiables)
Évitez les champs mutables dans un @Singleton car ils seraient partagés entre toutes les requêtes!
@Controller("/api/trends")
Marque la classe comme un contrôleur REST et définit le chemin de base des endpoints.
@Controller("/api/trends")
public class TrendController {
@Get // GET http://localhost:8080/api/trends
public String list() { ... }
@Get("/{id}") // GET http://localhost:8080/api/trends/123
public String getById(String id) { ... }
@Post // POST http://localhost:8080/api/trends
public String create() { ... }
}Le chemin spécifié dans @Controller est préfixé à tous les endpoints de la classe.
@Get, @Post, @Put, @Delete
Définissent le verbe HTTP de l’endpoint (CRUD operations).
@Controller("/users")
public class UserController {
@Get // GET /users
public List<User> list() { ... }
@Get("/{id}") // GET /users/123
public User getById(Long id) { ... }
@Post // POST /users
public User create(@Body User user) { ... }
@Put("/{id}") // PUT /users/123
public User update(Long id, @Body User user) { ... }
@Delete("/{id}") // DELETE /users/123
public void delete(Long id) { ... }
}Convention REST :
@Get→ Lecture (SELECT)@Post→ Création (INSERT)@Put→ Mise à jour complète (UPDATE)@Delete→ Suppression (DELETE)
@QueryValue
Récupère un paramètre de query string dans l’URL (?key=value).
@Get
public String search(
@QueryValue String keyword, // Obligatoire
@QueryValue(defaultValue = "US") String region // Optionnel avec défaut
) {
return "Searching for " + keyword + " in " + region;
}Avec les 2 params
GET http://localhost:8080/api/trends?keyword=java®ion=FRVariables :
keyword = "java"region = "FR"
Utilisations courantes :
- Filtres (
?category=tech&status=active) - Recherche (
?q=micronaut) - Pagination (
?page=2&size=20) - Tri (
?sort=createdAt&order=desc)
@PathVariable (ou juste le nom du paramètre)
Récupère une variable du chemin (path parameter).
@Get("/{id}")
public User getById(Long id) {
// id vient automatiquement du chemin
return userRepository.findById(id);
}Requête :
GET http://localhost:8080/users/123Résultat : id = 123
Dans Micronaut, pas besoin de @PathVariable explicite si le nom du paramètre correspond au placeholder !
Cas d’usage :
- Identifiant de ressource (
/users/123) - Slug d’article (
/posts/my-article) - Catégorie (
/products/electronics)
@Body
Récupère le corps de la requête HTTP et le transforme automatiquement en objet Java.
@Post
public User create(@Body User user) {
// user est automatiquement créé à partir du JSON reçu
return userService.save(user);
}Requête :
POST http://localhost:8080/users
Content-Type: application/json
{
"name": "Alice",
"email": "alice@example.com"
}Résultat dans le code :
user.getName() // "Alice"
user.getEmail() // "alice@example.com"Micronaut utilise Jackson pour la désérialisation JSON → Java automatiquement.
Quand l’utiliser :
@Post→ Créer une ressource@Put→ Remplacer complètement@Patch→ Modifier partiellement
Comparaison Query vs Path vs Body
Voici quand utiliser chaque type de paramètre dans vos endpoints REST.
| Type | Annotation | Exemple | Cas d’usage |
|---|---|---|---|
| Query String | @QueryValue | /users?name=alice&age=25 | Filtres, recherche, pagination, options |
| Path Variable | Aucune (auto) | /users/123 | Identifiant unique de ressource |
| Request Body | @Body | POST/PUT avec JSON | Créer/modifier des données complexes |
Query
// Filtrer une liste
@Get
public List<User> search(
@QueryValue(required = false) String name,
@QueryValue(defaultValue = "0") int page
) { ... }
// GET /users?name=alice&page=2Exemple Complet Commenté
@RequiredArgsConstructor // Génère le constructeur avec trendRepository
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) // Tous les champs → private final
@Controller("/api/trends") // Contrôleur REST sur /api/trends
public class TrendController {
GetTrendsUseCase getTrendsUseCase; // Devient: private final GetTrendsUseCase getTrendsUseCase
// Endpoint: GET http://localhost:8080/api/trends?keyword=java®ion=FR
@Get // Verbe HTTP GET
public TrendResponseDto getTrends(
@QueryValue String keyword, // Query param obligatoire
@QueryValue(defaultValue = "US") String region // Query param avec défaut
) {
return getTrendsUseCase.execute(keyword, region)
.map(TrendResponseDto::fromDomain)
.orElseThrow(() -> new RuntimeException("Unable to fetch trends"));
}
}Résumé Rapide
Tableau de référence rapide pour toutes les annotations du projet.
| Annotation | Type | Résumé | Exemple |
|---|---|---|---|
@RequiredArgsConstructor | Lombok | Constructeur champs final | Use cases, services |
@AllArgsConstructor | Lombok | Constructeur tous champs | Moins utilisé |
@FieldDefaults | Lombok | Modifier champs automatiquement | Évite private final |
@Value | Lombok | Classe immutable complète | DTOs, Value Objects |
@Singleton | Micronaut | Une seule instance | Use cases, repositories |
@Controller | Micronaut | API REST | Controllers REST |
@Get/@Post/@Put/@Delete | Micronaut | Verbe HTTP | CRUD endpoints |
@QueryValue | Micronaut | Paramètre URL (?key=value) | Filtres, recherche |
| Path param | Micronaut | Variable chemin (/users/123) | ID de ressource |
@Body | Micronaut | Corps requête JSON | Création/modification |
Tips & Best Practices
1. Injection de Dépendances
Micronaut injecte automatiquement les dépendances avec @RequiredArgsConstructor - pas besoin de @Inject ou @Autowired !
@Singleton
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository; // Injecté automatiquement
}2. Ordre des Annotations Lombok
L’ordre des annotations Lombok peut affecter le code généré.
✅ Correct
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class MyClass {
SomeService service;
}3. Retour JSON Automatique
Micronaut sérialise automatiquement vos objets en JSON avec Jackson.
@Get
public TrendResponseDto getTrends() {
return new TrendResponseDto("java", "FR", 85);
}Réponse HTTP automatique :
{
"keyword": "java",
"region": "FR",
"interestScore": 85
}4. Combo Gagnant
La combinaison la plus utilisée dans le projet :
@Singleton
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class GetTrendsUseCase {
TrendRepository repository;
public Optional<Trend> execute(String keyword) {
return repository.findByKeyword(keyword);
}
}Ressources
Prochaines étapes
Maintenant que vous maîtrisez les annotations, explorez les concepts fondamentaux de Micronaut et l’architecture hexagonale.