AEM : développer des composants avec HTL et Sling
Guide pratique pour créer des composants Adobe Experience Manager avec HTL (Sightly) et les Sling Models en Java — architecture, bonnes pratiques et exemples concrets.
Adobe Experience Manager repose sur deux piliers techniques pour le développement de composants : HTL (HTML Template Language, anciennement Sightly) côté template, et Sling Models côté logique Java. Comprendre comment ils s’articulent est indispensable pour produire un code propre, maintenable et conforme aux standards Adobe.
Architecture d’un composant AEM
Un composant AEM est un nœud JCR de type cq:Component. Sa structure minimale contient :
/apps/monprojet/components/moncomposant/
.content.xml ← définition du nœud JCR
moncomposant.html ← template HTL
_cq_dialog/ ← dialog de configuration auteur
models/
MoncomposantModel.java ← Sling Model
Le contenu du composant est stocké dans le JCR et lu via Sling. La logique métier est encapsulée dans un Sling Model, jamais dans le template HTL.
HTL : un template sans logique
HTL est intentionnellement limité : pas de boucles complexes, pas d’expressions arbitraires. C’est une contrainte volontaire pour forcer la séparation des responsabilités.
<!-- moncomposant.html -->
<sly data-sly-use.model="com.monprojet.models.MoncomposantModel" />
<div class="mon-composant" data-sly-test="${model.visible}">
<h2>${model.titre @ context='html'}</h2>
<p>${model.description @ context='html'}</p>
<ul data-sly-list.item="${model.liens}">
<li><a href="${item.url}">${item.label}</a></li>
</ul>
</div>
Points clés :
data-sly-useinstancie le Sling Modeldata-sly-testconditionne l’affichagedata-sly-listitère sur une collection@ context='html'permet le rendu HTML (à utiliser avec précaution)
Sling Models : la logique en Java
Le Sling Model est un bean Java annoté qui lit le contenu depuis le JCR et expose des méthodes au template.
@Model(
adaptables = SlingHttpServletRequest.class,
adapters = MoncomposantModel.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class MoncomposantModel {
@ValueMapValue
private String titre;
@ValueMapValue
private String description;
@ChildResource
private List<LinkItem> liens;
@SlingObject
private Resource resource;
public boolean isVisible() {
return StringUtils.isNotBlank(titre);
}
public String getTitre() {
return titre;
}
public String getDescription() {
return description;
}
public List<LinkItem> getLiens() {
return liens != null ? liens : Collections.emptyList();
}
}
@ValueMapValue injecte directement la propriété JCR correspondante au nom du champ. @ChildResource injecte un nœud enfant. @SlingObject donne accès à l’objet Sling.
La dialog auteur (_cq_dialog)
La dialog est ce que voit le rédacteur dans l’interface auteur d’AEM. Elle est définie en XML et repose sur des widgets Granite UI.
<!-- _cq_dialog/.content.xml -->
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Mon Composant"
sling:resourceType="cq/gui/components/authoring/dialog">
<content jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<titre jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Titre"
name="./titre" />
</items>
</column>
</items>
</content>
</jcr:root>
Bonnes pratiques
Séparation stricte : aucune logique dans HTL, aucun HTML dans le Sling Model. Le model expose des données, le template les affiche.
DefaultInjectionStrategy.OPTIONAL : évite les NullPointerException si une propriété JCR n’existe pas. Gérez les cas null dans le model.
Tester les models en isolation : les Sling Models sont des POJOs testables avec JUnit, sans démarrer AEM. Utilisez SlingContext de io.wcm.testing.mock.aem.
Versionner les dialogs : une modification de dialog sans migration de contenu peut casser les composants existants en production.
Conclusion
HTL et Sling Models forment un duo solide pour développer sur AEM. HTL garantit des templates lisibles et sécurisés, les Sling Models centralisent la logique et rendent le code testable. Maîtriser ce duo, c’est écrire du code AEM qui tient dans le temps — même quand une autre équipe doit le reprendre.
Amine MEGDICHE
Développeur AEM & Java Full Stack — Freelance depuis 2013