AEM Guide

Cómo Sling resuelve una petición hasta un componente de AEM

Cómo Sling convierte una URL en un Resource y luego en un componente AEM a través de sling:resourceType, las search paths /apps y /libs, y por qué sling:resourceSuperType es el patrón correcto para extender los Core Components.

slingresourcetypecore-componentshtl

Cuando AEM renderiza una página, lo que realmente ocurre por debajo es una resolución de Sling en dos pasos: primero una URL se convierte en un Resource, y después ese Resource se convierte en un componente —un script HTL o un servlet— que decide qué HTML se devuelve. Entender este pipeline explica por qué /apps puede sobreescribir /libs, por qué los Core Components se extienden con sling:resourceSuperType en lugar de sobrescribirlos directamente, y por qué un selector mal puesto puede romper la caché del Dispatcher.

De la URL al Resource

Cuando llega una petición como /content/mysite/es/inicio.html, Sling separa la ruta en resource path, selectores y extensión, y usa el ResourceResolver para mapear /content/mysite/es/inicio a un nodo JCR real. En un proyecto AEM ese nodo suele ser una página (cq:Page), pero lo que realmente importa para el renderizado es su nodo jcr:content (o el de un componente hijo), porque ahí es donde vive la propiedad sling:resourceType.

De Resource a componente: sling:resourceType

sling:resourceType no es una ruta absoluta: es una ruta relativa que Sling busca dentro de una lista ordenada de search paths. Por ejemplo, si un componente tiene:

sling:resourceType = "myproject/components/hero"

Sling busca un script (.html, .htl compilado a Java bajo el capó) o un servlet cuya ruta, relativa a alguno de los search paths, coincida con myproject/components/hero.

Las search paths de Sling: por qué /apps va antes que /libs

La configuración por defecto de Sling (resource.resolver.searchpath) es ["/apps", "/libs"]. Esto significa que, ante el mismo sling:resourceType, Sling siempre prueba primero el script que encuentre bajo /apps antes que el que encuentre bajo /libs. Este es el mecanismo técnico detrás del “overlay” clásico de AEM: si un recurso del producto vive en /libs/algo/componente y tú colocas un script en /apps/algo/componente, el tuyo gana.

En AEM as a Cloud Service, /libs es completamente inmutable: nunca vas a desplegar nada ahí. Este overlay por search path sigue siendo real para ciertos recursos de plataforma que todavía viven bajo /libs (por ejemplo, partes de Granite UI o de la consola de OSGi), pero no es el mecanismo que debes usar para extender los AEM Core Components — y ese es un error común.

Por qué los Core Components no se overlean: sling:resourceSuperType

Los AEM Core Components (core/wcm/components/...) se entregan como parte de las dependencias de tu proyecto y terminan instalados bajo /apps, no bajo /libs. Como ya están en /apps, no puedes “ganarles” poniendo algo en el mismo sling:resourceType bajo /apps sin sustituir por completo el componente del producto — perdiendo cualquier mejora futura que Adobe publique.

El patrón correcto es la herencia de componentes vía sling:resourceSuperType:

<!-- /apps/myproject/components/text/.content.xml -->
<jcr:root
    jcr:primaryType="cq:Component"
    jcr:title="Text"
    sling:resourceSuperType="core/wcm/components/text/v2/text"/>

Con esto, tu componente myproject/components/text hereda todo lo que no sobrescribas explícitamente (diálogo, script HTL, Sling:Model) del resourceSuperType. Si tu script HTL no define, por ejemplo, un bloque concreto, Sling sube por la cadena de resourceSuperType hasta encontrarlo en el Core Component. Esto es lo que permite personalizar solo el 10% que necesitas cambiar sin duplicar el 90% restante.

Selectores y extensión también cambian el script elegido

Los selectores y la extensión de la petición (.html, .json, un selector como .print) también entran en la resolución: Sling busca primero un script específico para esa combinación (text.print.html) antes de caer al script por defecto (text.html). Esto es exactamente lo que usa el JSON Exporter de AEM (.model.json) para servir la representación Sling Model de un componente sin tocar el script de renderizado normal.

Dónde esto importa en un proyecto AEM real