Date de publication : 12 août 2026
Temps de lecture : 21 min
Ce tutoriel commence par la correction ciblée de tests, introduit des murs qualité et met en œuvre des modifications de code en tenant compte du contexte du cycle de développement, des tests et des preuves de revue.

« Moderniser Java 8 vers Java 21 » peut sembler une tâche unique, mais ce n'est pas le cas. Cela concerne à la fois le build, l'environnement d'exécution, les dépendances, les API, la concurrence, les tests, les conteneurs et le comportement en production, souvent simultanément. Si vous demandez à un agent d'accomplir tout cela en un seul prompt, vous obtiendrez une merge request gigantesque que personne ne pourra relire sans risque.
Cursor, un agent de codage d'IA, excelle dans la partie ciblée de ce problème. Donnez-lui un test en échec ou un problème bien délimité, et il pourra examiner l'implémentation, expliquer ce qui s'est mal déroulé, proposer un correctif et exécuter les tests sans sortir du workflow de développement. Ce qu'il ne peut toutefois pas déterminer de lui-même, c'est ce que « sûr » signifie dans le cadre d'une migration en plusieurs étapes.
C'est là qu'intervient GitLab, avec GitLab Duo Agent Platform : il orchestre les workflows d'IA dans le reste du cycle de vie logiciel et est conçu pour certifier le travail des agents de codage. En raison de la hiérarchie des tickets avec les epics, le scénario est durable et vérifiable. Le serveur Model Context Protocol (MCP) de GitLab apporte le contexte du cycle de développement logiciel dans Cursor. Le CI/CD, le scan de sécurité, la revue de code, l'analyse d'impact et un test inter-services nous fournissent les preuves nécessaires avant de modifier le comportement en production.
Dans ce tutoriel, nous allons passer en revue trois cas d'utilisation de Cursor et de GitLab :
La progression est essentielle : commencez à petite échelle, ajoutez le contexte du projet, puis modernisez un périmètre. Cursor avance rapidement à l’intérieur de ce périmètre. Le flow Code Review, le flow Developer, le CI/CD, les approbations des propriétaires du code et l'analyse d'impact maintiennent cette vitesse en toute sécurité. Ce ne sont pas des points de contrôle facultatifs, mais des mécanismes qui garantissent que chaque merge request créée par un agent respecte les mêmes normes que toutes les autres.
Nous utilisons le collecteur de métriques HTTP Java de la plateforme Tanuki IoT pour ces trois cas d'utilisation. Il vérifie les points de terminaison HTTP, enregistre des métriques telles que le statut de réponse et les délais, et envoie les relevés à son backend de métriques Rust. Nous obtenons ainsi un périmètre d'application visible à moderniser et un véritable contrat backend à vérifier. Il y a quelque temps, nous avons développé le backend Rust dans le tutoriel Codex et GitLab, et il s'intègre désormais à l'architecture de production :
flowchart LR
subgraph sources["Sources de métriques HTTP"]
direction TB
health["État des points de terminaison"]
maintenance["Maintenance des points de terminaison"]
end
java["Collecteur de métriques HTTP Java"]
rust[("Backend de stockage des métriques Rust")]
java -->|"GET"| health
java -->|"GET"| maintenance
java -->|"POST/api/metrics"| rust
rust -->|"Réponse HTTP"| java
classDef source fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#0f172a
classDef focus fill:#dcfce7,stroke:#16a34a,stroke-width:3px,color:#0f172a
classDef backend fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a
class health,maintenance source
class java focus
class rust backend
Si vous souhaitez reproduire ce workflow dans votre propre environnement, commencez par importer et cloner le projet, puis ouvrez-le dans Cursor :
git clone https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector.git
cd java-http-metrics-collector
cursor .
Le projet comprend un fichier AGENTS.md contenant des instructions relatives au dépôt et des commandes Maven. Cursor peut utiliser ces instructions locales pour comprendre l'organisation du projet et la manière dont les modifications doivent être testées.

Le collecteur permet aux utilisateurs de configurer le code de statut HTTP qu'ils attendent d'un point de terminaison. Toutefois, l'implémentation traite chaque réponse 2xx comme réussie, et les erreurs 503 échouent systématiquement, même lorsqu'elles sont configurées comme prévu.
Le test de bout en bout expose déjà cette incohérence, mais le job CI/CD est autorisé à échouer. Ce qui a transformé un signal utile en bruit de fond accepté.

Le problème peut être reproduit localement. Ouvrez l'IDE Cursor avec un nouveau chat et commencez par décrire le problème observable directement dans le prompt :
Can you help me fix the end-to-end tests in this project? Please create an analysis first, then fix it, and run the tests again.
Cursor commence par retracer la configuration du point de terminaison dans HttpCollector et le test de bout en bout en échec, puis identifie la cause racine.

Une fois les tests ciblés et la suite de tests Maven complète réussis, créez une branche et une merge request. Le job de bout en bout, auparavant autorisé à échouer, peut devenir obligatoire lorsqu'il est déterministe et qu’il passe avec succès.
Can you create a git branch and merge request?
La merge request déclenche automatiquement le build et les tests CI/CD, ainsi que le scan de sécurité.

GitLab Duo Code Review passe ensuite en revue la modification ciblée en utilisant les instructions de revue spécifiques au projet Java.

Lorsque la revue identifie un problème concret, nous le traitons avec le flow Developer avant de fusionner. C'est précisément l'objectif : le flow Code Review garantit que chaque merge request créée par un agent répond aux mêmes exigences que n'importe quelle autre merge request, quelle que soit la rapidité avec laquelle Cursor l'a produite. La merge request reste la surface de collaboration et de décision.

Le correctif nous fournit une référence de comportement. Nous avons corrigé un véritable bogue sans le mélanger avec une migration de l'environnement d'exécution, et les tests protègent désormais le contrat de statut attendu pendant les travaux de modernisation qui suivront.
Regardez cette vidéo pour découvrir comment Cursor analyse et corrige les tests de bout en bout attendus :
Le premier correctif a fonctionné avec le seul contexte du dépôt. La prochaine tâche est bien plus ambitieuse : moderniser le collecteur de Java 8 vers Java 21.
Ce projet dispose déjà d'un contexte de planification dans l'epic de modernisation Java : éléments de travail enfants, discussions d'équipe, recherches avec merge requests, historique des pipelines, dépendances et résultats de sécurité. Ces détails ne se trouvent pas dans la copie locale. Plutôt que de tous les copier dans un seul prompt gigantesque, nous pouvons intégrer le contexte de GitLab dans Cursor grâce au MCP.
Assurez-vous que le serveur MCP de GitLab est activé sur votre instance ou votre groupe principal. Cursor utilise le transport HTTP pour se connecter directement sans dépendances supplémentaires.
Pour connecter Cursor au serveur MCP de GitLab :
mcpServers dans le fichier mcp.json ouvert. Pour GitLab.com, remplacez <gitlab.example.com> par gitlab.com. Pour GitLab Self-Managed ou GitLab Dedicated, utilisez l'URL de votre instance GitLab. {
"mcpServers": {
"GitLab": {
"type": "http",
"url": "https://<gitlab.example.com>/api/v4/mcp"
}
}
}

Vous pouvez maintenant démarrer un nouveau chat et poser une question basée sur les outils MCP disponibles de GitLab.
Lorsque Cursor s'authentifie auprès du MCP de GitLab, il agit avec votre identité GitLab existante. Il ne peut accéder qu'aux projets et ressources auxquels vous avez déjà accès. Le MCP apporte un contexte approuvé dans l'IDE ; il ne contourne pas les autorisations de GitLab.
L'epic de modernisation de Java 8 à 21 décompose le plan nécessaire en itérations plus petites, chaque artefact et chaque modification étant testable indépendamment.

La première étape consiste à s'assurer que l'infrastructure CI/CD teste à la fois Java 8 et Java 21 en parallèle. L'augmentation de la couverture de test dès le début de chaque tâche de modernisation est également obligatoire.
Ouvrez l'IDE Cursor et utilisez le prompt suivant pour récupérer le contexte de planification :
Please help me modernize this sensor from Java 8 to 21. We want to start with the base line for CI/CD builds in work item 14, and then also look into test coverage from 21. Start the implementation in a new Git branch called `maint-java-21` so we can continue testing different scenarios.
Après avoir terminé le travail sur le ticket de visibilité du build CI, Cursor peut également utiliser l'outil MCP create_workitem_note pour ajouter un commentaire récapitulatif dans le ticket.

La nouvelle merge request déclenche les pipelines CI/CD, ainsi que le flow Code Review, qui laisse des commentaires sur le guide de style de développement nécessitant une documentation.

Nous pouvons immédiatement traiter le retour dans l'interface GitLab en mentionnant le compte de service du flow Developer.
@duo-developer-<group-name> Can you help address the review feedback?
Ce prompt démarre une nouvelle session en arrière-plan, et nous pouvons nous concentrer sur d'autres tâches pendant ce temps. Nous pouvons également revenir dans l'IDE Cursor et utiliser son chat pour traiter le retour de revue dans la merge request.

Cursor met en œuvre les modifications et ajoute des commentaires dans les fils de discussion de la merge request à l'aide de l'outil MCP create_merge_request_note.

La modification conserve la base de référence Java 8 temporaire et ajoute une validation distincte du build et des tests Java 21. Ce changement rend la compatibilité visible dans le pipeline avant que le code source ne commence à utiliser des API exclusives à Java 21. Une fois ces murs qualité en place, chaque modification ultérieure pilotée par un agent est révisée, testée et traçable. C'est la même norme que nous appliquons à toute autre merge request, et c'est ce qui permet à Cursor d'avancer rapidement en toute sécurité.
Regardez cette vidéo pour découvrir comment Cursor utilise le MCP de GitLab pour préparer les murs qualité et traiter le retour de revue de code :
Le collecteur de métriques HTTP Java utilise actuellement l'API legacy HttpURLConnection de Java 8. Java 21 a modernisé la bibliothèque HTTP avec java.net.http.HttpClient, mais il ne s'agit pas d'un simple renommage mécanique. Les redirections, les en-têtes restreints, la portée des délais d'attente, les corps de réponse, les interruptions et la réutilisation des connexions peuvent tous se comporter différemment. C'est pourquoi l'implémentation est contenue dans un seul élément de travail bien délimité : Remplacer HttpURLConnection par java.net.http.HttpClient.
Ouvrez l'IDE Cursor avec un nouveau chat et demandez à mettre en œuvre les modifications.
Remarque : pour ce cas d'utilisation, nous souhaitons utiliser une configuration Docker Compose locale pour vérifier les modifications. Si vous souhaitez reproduire le comportement, installez Docker et Docker Compose ; sinon, supprimez le deuxième prompt.
We want to continue modernizing the app to Java 21 - use the same maint-java-21 branch, and start implementing issue 16.
Verify the changes locally using the docker compose setup, after making the changes.
Le serveur MCP de GitLab fournit le contexte du ticket, les critères d'acceptation, les dépendances et les discussions associées. Le premier ticket de modernisation du code reste délibérément synchrone et limité. Il remplace HttpURLConnection par un seul HttpClient réutilisable et n'ajoute pas de threads virtuels, ne modifie pas le modèle temporel, et ne corrige pas les dépendances non liées. Ce sont des améliorations précieuses, mais les combiner rendrait les changements de comportement plus difficiles à isoler, à réviser et à annuler.
Des tests HTTP locaux ciblés couvrent les méthodes, les en-têtes, les codes de statut attendus et inattendus, les redirections, les délais d'attente, les métadonnées de réponse, les échecs de connexion et les interruptions.

Le test fonctionnel Docker Compose prouve ensuite que les relevés authentifiés arrivent toujours dans le backend rust-metrics-store.

Si les pipelines CI/CD échouent après les modifications, utilisez les outils du serveur MCP de GitLab pour inspecter et corriger directement dans l'IDE Cursor sans changer de contexte.

Dans l'interface GitLab, vous pouvez utiliser le flow Fix CI/CD Pipeline ou demander l'aide de l'agent CI Expert.
GitLab CI/CD, GitLab Duo Code Review, l'analyse de sécurité et l'analyse d'impact assistée par l'IA fournissent les preuves finales dans la merge request. La revue humaine reste primordiale, notamment pour les frontières subtiles : toute différence de comportement intentionnelle doit être explicite dans la merge request, et non découverte après le déploiement.

Regardez cette vidéo pour découvrir comment Cursor et GitLab modernisent la bibliothèque HTTP du collecteur vers Java 21 :
Voici quelques conseils pour utiliser Cursor et GitLab ensemble.
Le troisième cas d'utilisation montre le flow Developer effectuant une analyse d'impact des changements majeurs. Vous pouvez transformer ce workflow en un flow personnalisé automatisé qui se déclenche lorsqu'une merge request est prête ou que le pipeline est au vert. Un contexte supplémentaire peut être récupéré depuis GitLab Orbit, qui fournit un graphe de contexte à travers le code, les éléments de travail, les merge requests, les vulnérabilités, et plus encore.
Vous pouvez commencer à inspecter le flow d'exemple dans le catalogue d'IA : MR Impact analysis (Orbit). Merci à ma collègue Fatima Sarah Kalid pour l'inspiration. Les flows personnalisés sont en disponibilité générale depuis GitLab 19.2.


Un fichier AGENTS.md aide Cursor et d'autres agents de codage à comprendre l'architecture du projet, les commandes, le style de code, les attentes en matière de tests et les limites. Conservez ces instructions à proximité du code et veillez à ce qu'elles soient suffisamment précises et concrètes pour être vérifiées.
Exemple tiré du fichier AGENTS.md dans le projet de collecteur de métriques HTTP Java :
# Java HTTP Metrics Collector - Agent Instructions
## Overview
The Java HTTP Metrics Collector is a REST API metrics collection sensor for the Tanuki IoT Platform. It monitors HTTP endpoints, collects performance metrics (response time, status codes, content length), and exports them in Prometheus text format. The application runs continuously with configurable collection intervals and supports concurrent endpoint monitoring.
## Code Style and Standards
### Java 8 Compatibility
- Do not modernize Java 8 code to Java 11+ features unless there is a GitLab issue or task specifically requesting modernization
- Target Java 8 for source and compilation: `maven.compiler.source=1.8` and `maven.compiler.target=1.8`
- Use Java 8 compatible patterns (e.g., anonymous inner classes instead of lambdas where appropriate)
### Documentation
- All public classes must have Javadoc describing purpose and usage
- All public methods must have Javadoc with `@param` and `@return` tags
- Include code examples in main class Javadoc
### Class Organization
- **Main entry point**: `HttpMetricsCollector` - orchestrates configuration loading, metric collection, and export
- **Collector**: `HttpCollector` - performs HTTP requests and collects metrics
- **Exporter**: `PrometheusExporter` - exports metrics in Prometheus text format
- **Models**: `CollectorConfig`, `EndpointConfig`, `HttpMetric` - data transfer objects
### Dependency Management
- Always use Maven for dependency management
- Use property-based version management for dependencies (e.g., `${jackson.version}`)
- Keep dependencies up-to-date in `pom.xml`
### Error Handling
- Use try-catch blocks with proper resource management (try-with-resources where applicable)
- Log errors using SLF4J Logger
- Gracefully handle configuration loading failures
- Implement proper shutdown hooks for resource cleanup
### Concurrency
- Use `ExecutorService` for concurrent HTTP requests
- Thread pool size is limited to the minimum of endpoint count and 10
- Properly shutdown executor service with timeout handling
- Use `Future` objects to collect results from concurrent tasks
Le flow GitLab Duo Code Review aide à maintenir les guides de style et les limites. Il s'attend à des instructions spécifiques dans le fichier .gitlab/duo/mr-review-instructions.yaml, par exemple pour Java :
# Custom instructions for GitLab Duo Code Review
instructions:
# General guidelines
- name: Code Review
instructions: |
1. Focus on correctness and performance
2. Ensure code comments and documentation are clear and concise
3. Be respectful and constructive in comments
- name: CI/CD Configuration
fileFilters:
- ".gitlab-ci.yml"
instructions: |
1. Do not use YAML anchors
2. Always use rules in jobs, avoid using `only`
# Java style guide
- name: Java Style Guide
fileFilters:
- "**/*.java"
instructions: |
1. Do not modernize Java 8 code to Java 11+ features, unless there is a GitLab issue or task specifically requesting modernization
2. All public classes must have Javadoc describing purpose and usage
3. All public methods must have Javadoc with @param and @return tags
4. Include code examples in main class Javadoc
5. All public methods must have at least one test case
6. Use httpbun.com for test endpoints (status codes, delays, JSON responses)
Au cours du processus de modernisation du code, la première directive relative à l'application de Java 8 devra être mise à jour.
Lorsqu'un workflow spécialisé devient répétable, capturez-le dans une compétence agentique. Les compétences sont chargées à la demande et ne remplissent pas la fenêtre de contexte par défaut.
Commencez avec un CI/CD fonctionnel, des tests et des décisions révisées afin que la compétence agentique reflète une pratique éprouvée plutôt qu'un plan non testé. Le ticket 24 dans l'epic de modernisation capture l'approche dans une compétence agentique ciblée de modernisation Java 21 et les versions ultérieures. Cette approche apporte une valeur au-delà de la merge request actuelle : les futures sessions d'agents pourront réutiliser les mêmes limites de sécurité au lieu de les reconstruire à partir de discussions antérieures.
Essayez cet exemple d'implémentation de compétence, inspiré de la compétence de maintenance Maven pour Java 8 existante :
---
name: java21-modernization
description: >-
Guide incremental Java 8 to Java 21+ modernization for the HTTP metrics
collector. Use when a GitLab work item asks for Java 21 CI visibility,
runtime/image upgrades, HttpClient migration, dependency or source API
modernization, or review of maint-java-21 style merge requests. Do not use
for routine Java 8 maintenance; prefer java8-maven-maintenance instead.
compatibility: Requires Maven, Docker Compose, and access to the owning GitLab work item.
---
# Java 21 Modernization
## Overview
Modernize in small, reviewable steps. The owning work item is authoritative.
Preserve collector → Rust metrics-store behavior unless the issue says otherwise.
Companion skill: `skills/java8-maven-maintenance/` for the Java 8 default path.
## Before editing
1. Read the owning issue/epic, `AGENTS.md`, `.gitlab-ci.yml`, `pom.xml`,
`Dockerfile`, and affected tests.
2. Record the current baseline:
- `maven.compiler.source` / `target`
- default CI image vs any `*:java-21` jobs
- container base image
- observable CLI/Compose behavior
3. Classify the change into **one** lane:
- CI visibility only
- runtime / image switch
- source / API modernization
- dependency upgrade
- tests / contract checks
Do not combine lanes in one MR unless the work item explicitly requires it.
## Workflow
Copy and track:
```text
Modernization progress:
- [ ] Baseline recorded
- [ ] Scoped to owning work item
- [ ] Target-JDK CI evidence available before JDK-only APIs
- [ ] Java 8 lane preserved until exit criteria say otherwise
- [ ] Unit / IT / Compose checks run
- [ ] MR documents risks, rollback, human decisions
```
## Guardrails
- Do not remove Java 8 compatibility unless the work item authorizes it.
- Do not introduce Java 21-only APIs before target-JDK CI evidence exists.
- Do not mix runtime upgrades with unrelated refactors.
- Do not claim performance wins without measurements.
- Preserve the Java → Rust API and authentication contract.
- Stop for a human decision when support policy, rollback, data format, or downstream compatibility is unclear.
## Validation
```bash
mvn -Dmaven.repo.local=.m2/repository test
mvn -Dmaven.repo.local=.m2/repository clean package
```
If Compose or container files change:
```bash
docker compose config --quiet
TANUKI_INGESTION_TOKEN=replace-me docker compose up -d --build
# confirm metric_sample logs and authenticated ingest still work
docker compose down -v
```
## Completion report
In the MR description, include:
1. Baseline before the change
2. Lane changed (CI / runtime / source / deps / tests)
3. Evidence run (commands + CI jobs)
4. Remaining risks and rollback
5. Human decisions still open
## Out of scope
- Broad "modernize everything to Java 21" prompts
- HTTP endpoint semantics unrelated to the JDK migration
(use `skills/http-endpoint-collector-behavior/`)
- Security triage unrelated to the migration slice
(use `skills/security-triage-java-sensor/`)
Les trois cas d'utilisation de ce tutoriel s'appuient les uns sur les autres. Cursor a corrigé un échec de test de bout en bout accepté en utilisant uniquement le contexte du dépôt. Ensuite, le serveur MCP de GitLab a apporté le plan de modernisation, afin que Cursor puisse mettre en place des murs qualité et boucler la boucle sur le retour de revue de GitLab Duo directement depuis l'IDE. Enfin, Cursor a effectué un changement Java 21 bien délimité et a remplacé HttpURLConnection par un HttpClient réutilisable, étayé par des tests ciblés, des exécutions d'ingestion inter-services, un pipeline, des scans de sécurité, une nomenclature logicielle, des preuves de revue et une analyse d'impact.
La modernisation d'un code source Java 8 legacy n'est pas plus sûre simplement parce qu'un agent écrit le code. Elle devient plus sûre parce que chaque modification est délimitée, révisée et testée dans Java 8 et Java 21, et traçable jusqu'à un élément de travail avec les décisions et les preuves qui le sous-tendent. Cursor gère l'implémentation. GitLab gère les preuves. Ensemble, ils font de la migration quelque chose en quoi une équipe peut avoir confiance.
Si vous souhaitez essayer ce workflow, commencez par un test qui expose un échec accepté dans une application legacy. Rendez ce test fiable, saisissez le plan de modernisation global dans GitLab et choisissez un périmètre que vous pouvez modifier et prouver indépendamment. L'agent aura ainsi une tâche ciblée, et l'équipe aura des preuves qu'elle pourra réviser.
Si vous n'utilisez pas encore GitLab Duo Agent Platform, commencez un essai gratuit.
Si vous utilisez déjà l'édition Gratuite de GitLab, vous pouvez vous inscrire à GitLab Duo Agent Platform en suivant quelques étapes simples.
Et si vous êtes déjà abonné à GitLab Premium ou GitLab Ultimate, lancez-vous simplement en activant GitLab Duo Agent Platform et en utilisant les GitLab Credits inclus dans votre abonnement.

L'IA tient-elle ses promesses à grande échelle ?
Le questionnaire ne prendra pas plus de 5 minutes.
Cet article de blog vous a plu ? Vous avez des questions ou des retours à nous faire ? Donnez votre avis en créant un nouveau sujet sur le forum de la communauté GitLab.
Faites-nous part de vos commentairesCommencez à développer plus rapidement dès aujourd'hui
Découvrez ce que votre équipe peut accomplir avec la plateforme d'orchestration intelligente pour le DevSecOps.