Migration Java 21 + Spring 6 de SAP Commerce Cloud : guide du développeur
SAP Commerce Lead, Spadoom AG
En septembre 2025, SAP a publié le framework update 2211-jdk21 pour SAP Commerce Cloud : depuis, la plateforme tourne sur Java 21 et Spring Framework 6 (SAP Help Portal : Framework Update). Deux dates en ont découlé. Les correctifs de sécurité des mises à jour 2211 basées sur Java 17 ont couru jusqu’à fin juin 2026. Et, selon l’annonce de SAP, les nouveaux builds ciblant Java 17 sont bloqués après le 31 août 2026.
Ces deux dates sont passées. Si votre projet a déjà basculé, ce guide vous aide à vérifier ce qui pourrait encore traîner. Sinon, il y a urgence : sans la mise à jour, vous ne pouvez plus construire ni déployer de modifications.
La mise à jour est plus qu’un changement de JDK. Spring 6 apporte le namespace Jakarta EE : javax.servlet, javax.validation et javax.annotation, les imports que les développeurs écrivent depuis quinze ans, deviennent jakarta.*. Cela touche les servlets, les filtres, les annotations de validation, la configuration Spring Security et potentiellement chaque extension spécifique. Les outils font l’essentiel du travail mécanique ; le reste relève de la véritable ingénierie.
En bref : avec 2211-jdk21, SAP Commerce Cloud tourne sur Java 21 et Spring 6. Les correctifs de sécurité pour Java 17 ont pris fin en juin 2026, et les nouveaux builds Java 17 sont bloqués après le 31 août 2026. La migration consiste à passer de
javax.*àjakarta.*, à réécrire les configurations Spring Security avecSecurityFilterChain, à vérifier les définitions XML de beans, la réflexion et les bibliothèques tierces, puis à tester à fond. OpenRewrite automatise l’essentiel du travail sur le namespace. Prévoyez deux à quatre semaines de migration et deux à trois semaines de tests de non-régression.
Ce qui change et pourquoi
Trois changements interviennent en même temps. Ils sont liés, mais ils cassent des choses différentes.
De Java 17 à Java 21. La version 2211, la génération exclusivement cloud de Commerce Cloud, a relevé le minimum à Java 17 ; 2211-jdk21 passe à Java 21, version à support long terme depuis septembre 2023 (OpenJDK). Java 21 apporte les virtual threads, le pattern matching pour switch, les record patterns et les sequenced collections. L’essentiel est additif et ne casse pas le code existant. Ce qui casse, c’est le code qui s’appuie par réflexion sur des éléments internes du JDK ou sur des API dont le comportement a changé.
De Spring 5 à Spring 6. Spring Framework 6 exige Java 17 ou plus et repose sur les API Jakarta EE 9+ (notes de migration vers Spring Framework 6). C’est le gros morceau : Spring 6 ne prend plus en charge le namespace javax.*. Si votre code étend des classes Spring ou implémente des interfaces qui référencent des types javax.*, il ne compile plus.
Le namespace Jakarta. Après la cession de Java EE par Oracle à l’Eclipse Foundation, les paquets ont été renommés de javax.* en jakarta.*. Un changement mécanique, mais omniprésent : chaque import, chaque nom de classe complet dans le XML, chaque référence sous forme de chaîne.
La manière dont ces changements s’insèrent dans l’architecture de Commerce Cloud est expliquée dans notre vue d’ensemble de SAP Commerce Cloud. Les autres nouveautés livrées par SAP cette année sont résumées dans les mises à jour pratiques de septembre 2026.
La chronologie
| Date | Événement |
|---|---|
| Septembre 2023 | Sortie de Java 21 en version LTS |
| Septembre 2025 | SAP publie le framework update 2211-jdk21 (Java 21, Spring 6) |
| Fin juin 2026 | Fin des correctifs de sécurité des mises à jour 2211 basées sur Java 17 |
| 31 août 2026 | Les nouveaux builds ciblant Java 17 sont bloqués |
La plupart des projets Commerce Cloud comptent des dizaines de milliers de lignes de Java spécifique réparties dans des dizaines d’extensions. Le seul changement de namespace produit des milliers de fichiers modifiés, et les tests prennent plus de temps que la migration elle-même.
Où vous en êtes en septembre 2026 : si vous êtes encore sur une version 2211 avec Java 17, vous travaillez sans correctifs de sécurité et ne pouvez plus livrer de modifications. Placez la migration en tête de votre feuille de route, gelez le développement de fonctionnalités et suivez la procédure ci-dessous. Vérifiez les règles actuellement en vigueur dans la documentation SAP et auprès du support SAP avant de planifier.
Checklist des changements incompatibles
Classés à peu près par fréquence et par impact.
Migration du namespace de javax.* vers jakarta.*
Le changement le plus répandu. Chaque référence à ces paquets doit être mise à jour :
| Ancien (javax.*) | Nouveau (jakarta.*) | Code concerné |
|---|---|---|
javax.servlet.* |
jakarta.servlet.* |
Filtres, contrôleurs spécifiques, wrappers de requête/réponse |
javax.validation.* |
jakarta.validation.* |
Bean validation, @NotNull, @Size, validateurs spécifiques |
javax.annotation.* |
jakarta.annotation.* |
@PostConstruct, @PreDestroy, @Resource |
javax.inject.* |
jakarta.inject.* |
@Inject, @Named |
javax.persistence.* |
jakarta.persistence.* |
Uniquement là où le code spécifique utilise JPA directement |
javax.ws.rs.* |
jakarta.ws.rs.* |
Points de terminaison JAX-RS (s’il y en a) |
Avant :
import javax.servlet.http.HttpServletRequest;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
public class CustomRequestValidator {
@NotNull
private String customField;
@PostConstruct
public void init() { /* ... */ }
}
Après :
import jakarta.servlet.http.HttpServletRequest;
import jakarta.annotation.PostConstruct;
import jakarta.validation.constraints.NotNull;
public class CustomRequestValidator {
@NotNull
private String customField;
@PostConstruct
public void init() { /* ... */ }
}
C’est surtout du rechercher-remplacer, mais attention aux chaînes littérales et aux fichiers XML où javax. apparaît comme nom complet. OpenRewrite en trouve la plupart ; un grep manuel trouve le reste.
Changements dans Spring Security
Spring Security 6 introduit plusieurs changements incompatibles qui touchent les projets Commerce Cloud. Le plus important : WebSecurityConfigurerAdapter a disparu.
Avant (Spring Security 5) :
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
Après (Spring Security 6) :
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
Les principaux changements :
WebSecurityConfigurerAdapterest supprimé ; on utilise des beansSecurityFilterChainauthorizeRequests()devientauthorizeHttpRequests()antMatchers()devientrequestMatchers()csrf(),cors()etsessionManagement()se configurent via la DSL lambda- Le
SecurityContextn’est plus enregistré automatiquement dans la session ; la persistance est explicite
Les configurations Spring Security spécifiques pour l’authentification sur la vitrine, la connexion B2B ou l’accès au Backoffice doivent être réécrites à la main. Il en va de même pour les extensions fondées sur l’ancien projet Spring Security OAuth, arrivé en fin de vie en 2022 : vérifiez dans la documentation SAP du framework update comment l’authentification OCC est désormais gérée avant de porter quoi que ce soit.
Changements dans Spring MVC
Spring 6 a supprimé plusieurs schémas dépréciés en 5.x :
CommonsMultipartResolverest remplacé parStandardServletMultipartResolver. Si vous avez configuré un téléversement de fichiers spécifique, mettez à jour le bean du resolver.- La correspondance avec barre oblique finale est désactivée par défaut.
/api/products/et/api/productssont désormais des routes différentes. Si la vitrine ou des clients d’API dépendent de l’ancienne tolérance, ajoutez des mappings explicites ou une redirection, et corrigez les URL. - La correspondance de chemins utilise par défaut
PathPatternParser, plus strict queAntPathMatcherpour certains motifs. Testez les mappings de vos contrôleurs spécifiques.
Là où le code spécifique utilise JPA ou Hibernate
SAP Commerce persiste les données via son propre système de types et sa couche de services, pas via JPA. Cette section ne concerne que les extensions qui embarquent leur propre pile JPA ou Hibernate, par exemple pour une base de données séparée. Pour elles, le passage à Jakarta signifie Hibernate 6, avec ses propres changements :
- Génération d’identifiants par séquence par défaut. Si vous comptez sur l’auto-incrément, définissez explicitement
strategy = GenerationType.IDENTITY. - Système de types remanié. Les implémentations spécifiques de
UserTypedoivent être mises à jour ; l’interface a changé de signature générique. - Annotation
@Typemodifiée.@Type(type = "yes_no")devient un convertisseur :
Avant :
@Type(type = "yes_no")
private Boolean active;
Après :
@Convert(converter = org.hibernate.type.YesNoConverter.class)
private Boolean active;
Changements du JDK entre 17 et 21
Vérifiez votre code et vos bibliothèques pour :
java.lang.SecurityManager: promis à la suppression depuis Java 17 (JEP 411) et inutilisable par défaut. Le code qui en installe un échoue à l’exécution.Thread.stop(),Thread.suspend(),Thread.resume(): lèvent désormais uneUnsupportedOperationException. Ils ont toujours été dangereux ; le code qui les appelle était déjà défectueux.- Encapsulation forte des éléments internes du JDK : les accès par réflexion à des paquets internes (
sun.misc,sun.reflectet d’autres) échouent sans options--add-opensexplicites. Mieux vaut mettre à jour la bibliothèque qu’ajouter des options. - Finalisation : promise à la suppression. Remplacez
finalize()parCleanerou try-with-resources.
Lancez ces vérifications tôt :
# Trouver les usages de SecurityManager
grep -rn "SecurityManager" --include="*.java" .
# Trouver les accès par réflexion aux éléments internes du JDK
grep -rn "sun\.misc\|sun\.reflect\|com\.sun\.proxy" --include="*.java" .
# Trouver les méthodes de contrôle de threads supprimées
grep -rn "\.stop()\|\.suspend()\|\.resume()" --include="*.java" .
OpenRewrite : automatiser l’essentiel du travail
OpenRewrite est un outil de refactoring automatique qui travaille sur l’arbre syntaxique et non sur le texte ; il traite donc correctement les imports, les noms complets et les références de types. C’est devenu l’outil de référence pour ce type de migration. Les recettes open source ci-dessous couvrent les parties génériques Java, Jakarta et Spring ; pour d’éventuels outils propres à Commerce, consultez la documentation SAP du framework update.
Étape 1 : ajouter le plugin OpenRewrite
SAP Commerce se construit avec Ant. Le plus simple pour exécuter OpenRewrite est un petit wrapper Gradle (ou Maven) qui pointe vers les dossiers sources de vos extensions spécifiques :
plugins {
id 'org.openrewrite.rewrite' version '7.3.0'
}
dependencies {
rewrite platform('org.openrewrite.recipe:rewrite-recipe-bom:3.5.0')
rewrite 'org.openrewrite.recipe:rewrite-migrate-java'
rewrite 'org.openrewrite.recipe:rewrite-spring'
}
rewrite {
activeRecipe(
'org.openrewrite.java.migrate.UpgradeToJava21',
'org.openrewrite.java.spring.framework.UpgradeSpringFramework_6_2',
'org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta'
)
}
Les recettes sont documentées sous UpgradeToJava21, JavaxMigrationToJakarta et UpgradeSpringFramework_6_2. Utilisez des versions à jour du plugin et du BOM.
Étape 2 : lancer d’abord un essai à blanc
./gradlew rewriteDryRun
Un rapport des différences est écrit dans build/reports/rewrite/. Examinez-le, cherchez les faux positifs et les modifications de fichiers qui ne vous appartiennent pas.
Étape 3 : appliquer la migration
./gradlew rewriteRun
Enregistrez le résultat dans un seul commit « migration du namespace », afin de pouvoir le relire et l’annuler proprement.
Étape 4 : exécuter séparément la recette Spring Security
rewrite {
activeRecipe(
'org.openrewrite.java.spring.security6.UpgradeSpringSecurity_6_2'
)
}
La recette Spring Security gère la suppression de l’adaptateur et les renommages, mais produit parfois du code qui compile sans respecter la logique de sécurité voulue. Vérifiez à la main chaque modification liée à la sécurité.
Ce que couvre OpenRewrite
- Imports de
javax.*versjakarta.* - Suppression de l’adaptateur Spring Security et passage à la DSL lambda
- Renommage de
antMatchers()enrequestMatchers() - Mise à jour de l’annotation Hibernate
@Type(là où JPA est utilisé) - Remplacement d’API pour Java 21
- Mise à jour des signatures Spring MVC
Ce qu’OpenRewrite manque
- Références de classes sous forme de chaîne :
Class.forName("javax.servlet.Filter") - Configuration XML : définitions de beans Spring dans
*-spring.xmlet*-beans.xmlqui référencent des classesjavax.* - Fichiers properties : références
javax.*dans les fichiers.properties - Chargement de types par réflexion : chargement dynamique de classes
- Processeurs d’annotations spécifiques qui analysent des annotations
javax.*
Ce qu’OpenRewrite ne peut pas corriger
C’est ici que les développeurs expérimentés font la différence.
Configurations Spring XML. Les extensions Commerce définissent de nombreux beans en XML. OpenRewrite ne transforme pas de façon fiable les références <bean class="javax.servlet.…">, alors passez chaque fichier Spring XML au crible :
# Trouver les références javax dans les configs Spring XML
grep -rn "javax\." --include="*-spring.xml" --include="*-beans.xml" .
Schémas AOP. Les expressions pointcut dans @Pointcut ou @Around sont des chaînes, pas des références de types :
Avant :
@Around("execution(* javax.servlet.http.HttpServlet+.do*(..))")
Après :
@Around("execution(* jakarta.servlet.http.HttpServlet+.do*(..))")
Code fondé sur la réflexion. Les extensions qui inspectent des types, chargent des beans dynamiquement ou créent des proxys peuvent contenir des chaînes javax.* codées en dur. Elles compilent et échouent à l’exécution.
Bibliothèques tierces. Si une extension dépend d’un JAR qui n’est pas encore passé à Jakarta EE, mettez-le à jour ou remplacez-le. Les JAR passerelles sont au mieux une solution transitoire.
Intercepteurs et système de types. Relisez les implémentations de PrepareInterceptor, ValidateInterceptor et LoadInterceptor, ainsi que tout code qui utilise des annotations de validation ou des types servlet dans ses signatures.
Stratégie de test
La migration produit des milliers de changements mécaniques parmi lesquels se cachent quelques changements de fond. La stratégie de test doit les trouver sans se noyer dans le volume.
Tests unitaires
Lancez d’abord les tests unitaires existants : c’est le retour le plus rapide, et à ce stade ils trouvent plus de vraies régressions qu’une relecture de code attentive. Corrigez d’abord les erreurs de compilation (changements de namespace oubliés), puis les échecs d’assertion (changements de comportement dans Spring 6).
Les tests doivent généralement être adaptés en raison :
- d’une configuration des mocks modifiée (les API de test de Spring Security ont changé)
- de changements dans la configuration du contexte de test Spring
- d’une correspondance de chemins plus stricte dans les tests MVC
Tests d’intégration
Exécutez la suite d’intégration complète sur une installation locale en Java 21 :
ant alltests -Dtestclasses.packages=com.yourcompany.*
Ils révèlent ce que les tests unitaires ne voient pas : des erreurs de câblage des beans après le changement de namespace, des chaînes de filtres de sécurité mal configurées et des ClassNotFoundException à l’exécution provenant du XML.
Régression des performances
Java 21 devrait améliorer les performances, mais vérifiez :
- Temps de démarrage : comparez les démarrages à froid entre les builds Java 17 et Java 21
- Empreinte mémoire : surveillez l’utilisation du tas sous charge
- Débit : lancez vos tests de charge habituels et comparez les temps de réponse
- Ramasse-miettes : ZGC générationnel est disponible en Java 21 ; évaluez-le pour les charges sensibles à la latence avant de basculer
Vérifications propres à SAP
- Imports ImpEx : vérifiez que tous les fichiers ImpEx s’importent encore, en particulier ceux qui référencent des classes Java
- Backoffice : contrôlez que les types, éditeurs et widgets spécifiques s’affichent correctement
- Tests de fumée de la vitrine : panier, checkout, paiement, confirmation de commande
- Tests des API OCC : appelez vos points de terminaison OCC spécifiques et vérifiez les contrats de requête et de réponse, authentification comprise
La migration étape par étape
Dix étapes, dans cet ordre.
Étape 1 : inventorier le code spécifique. Comptez les extensions spécifiques, les lignes de Java, les fichiers Spring XML et les dépendances tierces.
# Compter les fichiers Java et les lignes
find . -name "*.java" -path "*/src/*" | wc -l
find . -name "*.java" -path "*/src/*" -exec cat {} \; | wc -l
# Compter les configs Spring XML
find . -name "*-spring.xml" -o -name "*-beans.xml" | wc -l
# Lister les JAR tiers
find . -name "*.jar" -path "*/lib/*" | sort
Étape 2 : créer une branche de migration. La migration touche des centaines de fichiers ; séparez-la du développement de fonctionnalités.
git checkout -b migration/java21-spring6
Étape 3 : mettre à jour le build. Passez le JDK local et la CI à Java 21, et réglez commerceSuiteVersion dans le manifest.json sur une version 2211-jdk21 actuelle.
Étape 4 : migration du namespace avec OpenRewrite. Appliquez JavaxMigrationToJakarta et UpgradeToJava21, puis faites un commit.
Étape 5 : exécuter les recettes Spring 6. Appliquez les recettes Spring Framework et Spring Security, relisez-les et faites un commit séparé.
Étape 6 : corriger ce qu’OpenRewrite a manqué. Cherchez les références javax. restantes dans le XML, les properties et les chaînes littérales.
# Trouver TOUTES les références javax restantes
grep -rn "javax\." --include="*.xml" --include="*.properties" \
--include="*.java" .
Étape 7 : corriger les erreurs de compilation. Construisez et traitez chaque erreur ; en général des changements d’API Spring Security, des comportements du JDK supprimés ou des bibliothèques obsolètes.
Étape 8 : lancer les tests unitaires et corriger les échecs. Réparez les tests qui échouent à cause de changements d’API ; ne les supprimez pas.
Étape 9 : tests d’intégration sur un environnement Java 21. Déployez sur un environnement de préproduction Commerce Cloud en 2211-jdk21 et lancez la suite complète de tests d’intégration et de fumée.
Étape 10 : valider les performances et passer en production. Lancez les tests de charge, comparez avec la référence Java 17 et déployez.
Pièges fréquents
ClassNotFoundException à l’exécution. Tout compile, mais un bean Spring échoue au démarrage parce qu’une configuration XML référence encore javax.servlet.Filter sous forme de chaîne. Passez toujours les fichiers XML au crible.
Spring Security laisse tout passer (ou rien). Lors du passage de WebSecurityConfigurerAdapter à SecurityFilterChain, un .build() manquant ou un @Configuration oublié fait retomber Spring sur une configuration par défaut. Testez explicitement l’authentification et les autorisations.
Conflits de JAR tiers. D’après notre expérience, c’est le piège qui coûte le plus de jours. Une bibliothèque embarque ses propres classes javax.* et, après la migration, javax.servlet et jakarta.servlet se retrouvent tous deux dans le classpath. Résultat : une ClassCastException à l’exécution, car un jakarta.servlet.http.HttpServletRequest n’est pas un javax.servlet.http.HttpServletRequest, même si les méthodes sont identiques. Retirez ou mettez à jour le JAR en cause.
Références de classes dans les ImpEx. Les fichiers ImpEx peuvent référencer des classes Java pour des traducteurs et des processeurs d’import spécifiques. Si ces classes dépendent de types javax.*, l’import échoue avec un message obscur. Vérifiez vos fichiers ImpEx.
Versions divergentes dans le pipeline de build. En local, Java 21 tourne, mais le pipeline de CI ou le manifest.json pointe encore vers une version Java 17. Tout fonctionne en local, le déploiement échoue. Mettez les deux à jour avant la première tentative de déploiement.
La migration vers Java 21 et Spring 6 est mécanique par nature et large par son étendue. OpenRewrite prend en charge de manière fiable le fastidieux travail sur le namespace. Reste le travail d’ingénierie soigné : réécrire Spring Security, les configurations XML, la réflexion, les bibliothèques et des tests approfondis. Si vous prévoyez aussi des changements plus larges de la plateforme, notre checklist de migration pour SAP Commerce couvre le reste du chemin.
Besoin d’aide pour évaluer le périmètre dans votre code ? Contactez-nous. Nous connaissons cette mise à jour par notre propre travail sur Commerce Cloud. Notre façon de travailler avec la plateforme est présentée sur notre page SAP Commerce Cloud, et si vous comparez des partenaires d’implémentation, notre panorama des meilleurs partenaires SAP Commerce Cloud en Suisse vous y aidera.
Demandez à Spadoom
Des réponses fondées sur ce que Spadoom a publié sur ce site, avec des liens vers les pages sources.
Essayez l'une de ces questions
Réponses générées par IA. À vérifier avant d'agir. Les questions sont enregistrées de manière anonyme, sans adresse IP, afin d'améliorer nos contenus. Merci de ne pas saisir de données personnelles.
SAP Commerce Cloud partenaire d'implémentation
Spadoom est le partenaire d'implémentation SAP Commerce Cloud en Suisse, Allemagne, Autriche et Italie. Médiane de go-live de 14 semaines. Clients en production dans tout le DACH.
Articles associes
SAP Commerce on-premise après le 31 juillet 2026 : ce qui a changé et vos quatre options
La maintenance mainstream de SAP Commerce on-premise a pris fin le 31 juillet 2026. Ce guide explique ce qui a changé, ce que couvre encore la maintenance spécifique client, où se cachent les coûts du statu quo et comment les quatre options réalistes se comparent en délai, en risque et en résultat final.
SAP Hybris End of Life : la checklist complète de migration pour 2026
La maintenance principale de SAP Commerce on-premise (anciennement Hybris) a pris fin le 31 juillet 2026. Ce que cela signifie pour vous aujourd'hui, ce qui passe de Hybris à Commerce Cloud et la checklist avec laquelle nous migrons : évaluation, architecture, réalisation, mise en production et les semaines qui suivent.
De SAP Hybris à Commerce Cloud en 90 jours : un playbook de migration
Comment une plateforme SAP Hybris de taille moyenne arrive sur SAP Commerce Cloud en 90 jours : 30 jours de préparation, trois sprints, mise en production. La méthode derrière nos lancements commerce les plus rapides, et ce qu'il faut faire maintenant que la maintenance principale de l'on-premise a pris fin.