Adobe Experience Manager (AEM) basiert auf umfassender Open-Source-Software-Technologie, über die zahlreiche Java-APIs zur Verwendung während der Entwicklung bereitgestellt werden. In diesem Artikel werden die wichtigsten APIs sowie deren Verwendungszeitpunkt und -grund untersucht.
AEM basiert auf 4 primären Java-API-Sets.
Adobe Experience Manager (AEM)
Apache Sling Web Framework
JCR (Apache Jackrabbit Oak)
OSGi (Apache Felix)
Die allgemeine Regel besteht darin, die APIs/Abstraktionen in der folgenden Reihenfolge vorzuziehen:
Wenn eine API von AEM bereitgestellt wird, ziehen Sie sie vor Sling, JCR und OSGi. Wenn AEM keine API bereitstellt, bevorzugen Sie Sling über JCR und OSGi.
Diese Reihenfolge ist eine allgemeine Regel, d. h. es gibt Ausnahmen. Folgende Gründe können von dieser Regel abweichen:
Bekannte Ausnahmen, wie unten beschrieben.
In einer API auf höherer Ebene ist die erforderliche Funktionalität nicht verfügbar.
Die Verwendung im Kontext von vorhandenem Code (benutzerdefinierter oder AEM Produktcode), der selbst eine weniger bevorzugte API verwendet, und die Kosten für den Wechsel zur neuen API sind nicht zu rechtfertigen.
AEM APIs bieten Abstraktionen und Funktionen, die speziell für produktionsierte Anwendungsfälle gelten.
AEM PageManager und Seite APIs bieten Abstraktionen für cq:Page
-Knoten in AEM, die Webseiten darstellen.
Diese Knoten sind über verfügbar. Sling APIs als Ressourcen und JCR-APIs als Knoten AEM APIs bieten Abstraktionen für gängige Anwendungsfälle. Durch die Verwendung der AEM-APIs wird ein konsistentes Verhalten zwischen AEM Produkt und den zu AEM Anpassungen und Erweiterungen sichergestellt.
AEM APIs haben eine Präferenz für interne Pakete, die durch die folgenden Java-Pakete identifiziert wird, in der Reihenfolge ihrer Präferenz:
com.adobe.cq
com.adobe.granite
com.day.cq
com.adobe.cq
unterstützt Anwendungsfälle für Produkte. com.adobe.granite
unterstützt produktübergreifende Anwendungsfälle wie Workflows oder Aufgaben (die produktübergreifend verwendet werden): AEM Assets, Sites usw.).
com.day.cq
enthält "ursprüngliche"APIs. Diese APIs richten sich an zentrale Abstraktionen und Funktionen, die vor und/oder rund um den Erwerb von Day CQ. Diese APIs werden unterstützt und sollten nicht vermieden werden, es sei denn, com.adobe.cq
oder com.adobe.granite
eine (neuere) Alternative bereitstellen.
Neue Abstraktionen wie Content Fragments und Experience Fragments werden im com.adobe.cq
Leerzeichen anstelle von com.day.cq
weiter unten beschrieben.
AEM unterstützt mehrere Abfragesprachen. Die drei Hauptsprachen sind JCR-SQL2, XPath und AEM Query Builder.
Das wichtigste Anliegen ist die Beibehaltung einer konsistenten Abfragesprache in der gesamten Codebasis, um die Komplexität zu reduzieren und die Kosten für das Verständnis zu reduzieren.
Alle Abfragesprachen haben im Grunde dieselben Leistungsprofile wie Apache Oak überträgt sie für die endgültige Ausführung der Abfrage an JCR-SQL2, und die Konvertierungszeit an JCR-SQL2 ist im Vergleich zur Abfragezeit selbst vernachlässigbar.
Die bevorzugte API lautet AEM Query Builder, die Abstraktion auf höchster Ebene und eine robuste API zum Erstellen, Ausführen und Abrufen von Ergebnissen für Abfragen bereitstellt und Folgendes bereitstellt:
Einfache, parametrisierte Abfrageerstellung (Abfrageparameter, modelliert als Karte)
Nativ Java-API und HTTP-APIs
AEM Unterstützung gemeinsamer Abfrageanforderungen
Erweiterbare API, die die Entwicklung benutzerdefinierter Abfrageeigenschaften
JCR-SQL2 und XPath können direkt über Sling und JCR-APIs, die Ergebnisse zurückgibt Sling Ressourcen oder JCR-Knotenzurück.
AEM QueryBuilder-API leckt ein ResourceResolver-Objekt. Gehen Sie wie folgt vor, um dieses Leck zu vermeiden Codebeispiel.
Apache Sling ist das RESTful-Web-Framework, das AEM unterstützt. Sling bietet HTTP-Anforderungsrouting, modelliert JCR-Knoten als Ressourcen, bietet Sicherheitskontext und vieles mehr.
Sling APIs bieten den zusätzlichen Vorteil, dass sie für Erweiterungen erstellt werden. Dies bedeutet, dass es häufig einfacher und sicherer ist, das Verhalten von Anwendungen zu erweitern, die mit Sling APIs als die weniger erweiterbaren JCR-APIs.
Zugreifen auf JCR-Knoten als Sling Resources und Zugriff auf ihre Daten über ValueMaps.
Bereitstellen von Sicherheitskontext über ResourceResolver.
Erstellen und Entfernen von Ressourcen über das ResourceResolver Methoden zum Erstellen/Verschieben/Kopieren/Löschen.
Aktualisieren von Eigenschaften über ModifiableValueMap.
Bausteine für die Anforderungsverarbeitung
Bausteine für die asynchrone Arbeitsverarbeitung
Die JCR (Java Content Repository) 2.0-APIs ist Teil einer Spezifikation für JCR-Implementierungen (im Falle von AEM, Apache Jackrabbit Oak). Alle JCR-Implementierungen müssen diesen APIs entsprechen und implementieren. Daher ist sie die niedrigste API für die Interaktion mit AEM Inhalt.
Das JCR selbst ist ein hierarchischer/baumbasierter NoSQL-Datenspeicher, der AEM als Content-Repository verwendet. Das JCR verfügt über eine Vielzahl unterstützter APIs, von Inhalts-CRUD bis hin zur Abfrage von Inhalten. Trotz dieser robusten API werden sie selten gegenüber der übergeordneten AEM bevorzugt. Sling Abstraktionen.
Bevorzugen Sie immer die JCR-APIs gegenüber den Apache Jackrabbit Oak-APIs. Die JCR-APIs sind für interagieren mit einem JCR-Repository verwenden, während die Oak-APIs für Umsetzung ein JCR-Repository.
Während das JCR AEM Content Repository ist, sind seine APIs NICHT die bevorzugte Methode für die Interaktion mit dem Inhalt. Bevorzugen Sie stattdessen die AEM-APIs (Seite, Assets, Tag usw.) oder Sling Resource APIs , da sie bessere Abstraktionen bieten.
Die breite Verwendung der Sitzungs- und Knotenschnittstellen von JCR-APIs in einer AEM Anwendung ist vom Code-Geruch abhängig. Sichern Sling APIs sollten nicht stattdessen verwendet werden.
JCR-Beobachtung (Überwachen auf JCR-Ereignisse)
Erstellen von tiefen Knotenstrukturen
Es gibt kaum Überschneidungen zwischen den OSGi-APIs und den APIs auf höherer Ebene (AEM, Sling, und JCR) sowie die Notwendigkeit, OSGi-APIs zu verwenden, ist selten und erfordert ein hohes Maß an AEM Entwicklungskompetenz.
OSGi definiert eine Spezifikation, die alle OSGi-Container implementieren und erfüllen müssen. AEM OSGi-Implementierung stellt Apache Felix mehrere eigene APIs bereit.
org.osgi
) über Apache Felix-APIs (org.apache.felix
).OSGi-Anmerkungen zum Deklarieren von OSGi-Diensten und -Komponenten.
OSGi-APIs für dynamisch im Code befindliche Deaktivieren/Registrieren von OSGi-Diensten/Komponenten.
Im Folgenden finden Sie allgemeine Ausnahmen von den oben definierten Regeln.
Bei der Behandlung von OSGi-Abstraktionen auf niedriger Ebene, z. B. beim Definieren oder Lesen in OSGi-Komponenteneigenschaften, werden die neueren Abstraktionen bereitgestellt von org.osgi
werden gegenüber Sling-Abstraktionen auf höherer Ebene bevorzugt. Die konkurrierenden Sling-Abstraktionen wurden nicht als @Deprecated
und empfiehlt org.osgi
Alternative.
Beachten Sie außerdem, dass die Definition des OSGi-Konfigurationsknotens cfg.json
über sling:OsgiConfig
Format.
Voreinstellen com.day.cq.dam.api
over com.adobe.granite.asset.api
.
com.day.cq
Die Assets-APIs bieten umfassendere Tools für AEM Anwendungsfälle der Asset-Verwaltung.@SlingServlet
@SlingFilter
Im Folgenden finden Sie hilfreiche Java-Codefragmente, die Best Practices für gängige Anwendungsfälle mit diskutierten APIs veranschaulichen. Diese Snippets zeigen auch, wie Sie von weniger bevorzugten APIs zu bevorzugten APIs wechseln können.
Seit AEM 6.2 wird die Sling ResourceResolver is AutoClosable
in try-with-resources -Anweisung. Mithilfe dieser Syntax wird ein expliziter Aufruf an resourceResolver .close()
nicht benötigt.
@Reference
ResourceResolverFactory rrf;
...
Map<String, Object> authInfo = new HashMap<String, Object>();
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, jcrSession);
try (ResourceResolver resourceResolver = rrf.getResourceResolver(authInfo)) {
// Do work with the resourceResolver
} catch (LoginException e) { .. }
ResourceResolvers muss manuell in einem finally
-Block, wenn die oben dargestellte Technik zum automatischen Schließen nicht verwendet werden kann.
@Reference
ResourceResolverFactory rrf;
...
Map<String, Object> authInfo = new HashMap<String, Object>();
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, jcrSession);
ResourceResolver resourceResolver = null;
try {
resourceResolver = rrf.getResourceResolver(authInfo);
// Do work with the resourceResolver
} catch (LoginException e) {
...
} finally {
if (resourceResolver != null) { resourceResolver.close(); }
}
Resource resource = ResourceResolver.getResource("/path/to/the/resource");
Resource resource = resourceResolver.getResource(node.getPath());
DamUtil.resolveToAsset(..)
löst alle Ressourcen unter dam:Asset
zum Asset-Objekt hinzu, indem Sie nach Bedarf die Struktur nach oben navigieren.
Asset asset = DamUtil.resolveToAsset(resource);
Die Anpassung einer Ressource an ein Asset setzt voraus, dass die Ressource selbst die dam:Asset
Knoten.
Asset asset = resource.adaptTo(Asset.class);
pageManager.getContainingPage(..)
löst alle Ressourcen unter cq:Page
in das Seitenobjekt ein, indem Sie nach Bedarf die Baumstruktur nach oben navigieren.
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
Page page = pageManager.getContainingPage(resource);
Page page2 = pageManager.getContainingPage("/content/path/to/page/jcr:content/or/component");
Die Anpassung einer Ressource an eine Seite setzt voraus, dass die Ressource selbst die cq:Page
Knoten.
Page page = resource.adaptTo(Page.class);
Verwenden Sie die Getter des Seitenobjekts, um bekannte Eigenschaften zu erhalten (getTitle()
, getDescription()
usw.) und page.getProperties()
um [cq:Page]/jcr:content
ValueMap zum Abrufen anderer Eigenschaften.
Page page = resource.adaptTo(Page.class);
String title = page.getTitle();
Calendar value = page.getProperties().get("cq:lastModified", Calendar.getInstance());
Die Asset-API bietet praktische Methoden zum Lesen von Eigenschaften aus dem [dam:Asset]/jcr:content/metadata
Knoten. Beachten Sie, dass dies keine ValueMap ist. Der zweite Parameter (Standardwert und automatische Umwandlung) wird nicht unterstützt.
Asset asset = resource.adaptTo(Asset.class);
String title = asset.getMetadataValue("dc:title");
Calendar lastModified = (Calendar) asset.getMetadata("cq:lastModified");
Wenn Eigenschaften an Orten (Eigenschaften oder relative Ressourcen) gespeichert werden, an denen die AEM-APIs (Seite, Asset) nicht direkt zugreifen können, wird die Sling Ressourcen und ValueMaps können zum Abrufen der Daten verwendet werden.
ValueMap properties = resource.getValueMap();
String value = properties.get("jcr:title", "Default title");
String relativeResourceValue = properties.get("relative/propertyName", "Default value");
In diesem Fall muss das AEM-Objekt möglicherweise in eine Sling Resource , um die gewünschte Eigenschaft oder Unterressource effizient zu finden.
Resource resource = page.adaptTo(Resource.class);
Resource resource = asset.adaptTo(Resource.class);
Verwendung Slings ModifiableValueMap , um Eigenschaften in Knoten zu schreiben. Dies kann nur in den unmittelbaren Knoten schreiben (relative Eigenschaftspfade werden nicht unterstützt).
Notieren Sie den Aufruf von .adaptTo(ModifiableValueMap.class)
erfordert Schreibberechtigungen für die Ressource, sonst wird null zurückgegeben.
ModifiableValueMap properties = resource.adaptTo(ModifiableValueMap.class);
properties.put("newPropertyName", "new value");
properties.put("propertyNameToUpdate", "updated value");
properties.remove("propertyToRemove");
resource.getResourceResolver().commit();
Verwenden Sie PageManager immer, um Seiten zu erstellen, während eine Seitenvorlage benötigt wird. Dies ist erforderlich, um Seiten in AEM ordnungsgemäß zu definieren und zu initialisieren.
String templatePath = "/conf/my-app/settings/wcm/templates/content-page";
boolean autoSave = true;
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
pageManager.create("/content/parent/path", "my-new-page", templatePath, "My New Page Title", autoSave);
if (!autoSave) { resourceResolver.commit(); }
ResourceResolver unterstützt grundlegende Vorgänge zum Erstellen von Ressourcen. Beim Erstellen von Abstraktionen auf höherer Ebene (AEM Seiten, Assets, Tags usw.) die von den jeweiligen Managern bereitgestellten Methoden verwenden.
resourceResolver.create(parentResource, "my-node-name", new ImmutableMap.Builder<String, Object>()
.put("jcr:primaryType", "nt:unstructured")
.put("jcr:title", "Hello world")
.put("propertyName", "Other initial properties")
.build());
resourceResolver.commit();
ResourceResolver unterstützt das Entfernen einer Ressource. Beim Erstellen von Abstraktionen auf höherer Ebene (AEM Seiten, Assets, Tags usw.) die von den jeweiligen Managern bereitgestellten Methoden verwenden.
resourceResolver.delete(resource);
resourceResolver.commit();