Best practice per le API Java™
Adobe Experience Manager (AEM) è basato su uno stack di software open-source che espone molte API Java™ da utilizzare durante lo sviluppo. Questo articolo esplora le principali API e quando e perché dovrebbero essere utilizzate.
L’AEM è basato su quattro set API Java™ primari.
-
Adobe Experience Manager (AEM)
- Astrazioni di prodotto come pagine, risorse, flussi di lavoro, ecc.
-
Framework web Apache Sling
- Astrazioni REST e basate su risorse come risorse, mappe del valore e richieste HTTP.
-
JCR (Apache Jackrabbit Oak)
- Astrazioni di dati e contenuti come nodo, proprietà e sessioni.
-
OSGi (Apache Felix)
- Astrazioni dei contenitori di applicazioni OSGi come servizi e componenti (OSGi).
Preferenza API Java™ "rule of thumb"
La regola generale consiste nel preferire le API/astrazioni nel seguente ordine:
- AEM
- Sling
- JCR
- OSGi
Se un’API è fornita dall’AEM, preferiscila rispetto a Sling, JCR e OSGi. Se l’AEM non fornisce un’API, preferisci Sling su JCR e OSGi.
Questo ordine è una regola generale, il che significa che esistono eccezioni. Motivi accettabili per derogare a questa regola sono:
-
Eccezioni ben note, come descritto di seguito.
-
La funzionalità richiesta non è disponibile in un’API di livello superiore.
-
Operare nel contesto di un codice esistente (codice prodotto personalizzato o AEM) che utilizza un’API meno preferita e il costo per passare alla nuova API è ingiustificabile.
- È meglio utilizzare in modo coerente l’API di livello inferiore piuttosto che creare un mix.
API AEM
Le API dell’AEM forniscono astrazioni e funzionalità specifiche per i casi d’uso prodotti.
Ad esempio, AEM PageManager e Pagina Le API forniscono astrazioni per cq:Page
nodi in AEM che rappresentano pagine web.
Mentre questi nodi sono disponibili tramite Sling API come Risorse e API JCR come Nodi, le API AEM forniscono astrazioni per casi d’uso comuni. L’utilizzo delle API dell’AEM garantisce un comportamento coerente tra l’AEM del prodotto e le personalizzazioni ed estensioni dell’AEM.
com.adobe.* rispetto a com.day.* API
Le API AEM hanno una preferenza intra-pacchetto, identificata dai seguenti pacchetti Java™, in ordine di preferenza:
com.adobe.cq
com.adobe.granite
com.day.cq
Il com.adobe.cq
supporta casi di utilizzo di prodotti, mentre com.adobe.granite
supporta casi di utilizzo per più piattaforme, ad esempio flusso di lavoro o attività (utilizzate tra prodotti diversi: AEM Assets, Sites e così via).
Il com.day.cq
Il pacchetto contiene API "originali". Queste API rispondono alle astrazioni e alle funzionalità di base che esistevano prima e/o intorno all’acquisizione di da parte di Adobe di Day CQ. Queste API sono supportate e devono essere evitate, a meno che com.adobe.cq
o com.adobe.granite
I pacchetti NON forniscono un’alternativa (più recente).
Nuove astrazioni come Content Fragments e Experience Fragments sono integrate in com.adobe.cq
spazio anziché com.day.cq
descritte di seguito.
API di query
L’AEM supporta più linguaggi di query. Le tre lingue principali sono JCR-SQL2, XPath e Generatore di query AEM.
La preoccupazione più importante è mantenere un linguaggio di query coerente in tutta la base di codice, per ridurre la complessità e i costi di comprensione.
Tutti i linguaggi di query hanno effettivamente gli stessi profili di prestazioni, come Apache Oak li trasferisce a JCR-SQL2 per l’esecuzione finale della query e il tempo di conversione a JCR-SQL2 è trascurabile rispetto al tempo di query stesso.
L’API preferita è Generatore di query AEM, che è l’astrazione di livello più alto e fornisce una solida API per la costruzione, l’esecuzione e il recupero dei risultati delle query, oltre a:
-
Costruzione di query con parametri semplice (parametri di query modellati come una mappa)
-
Nativa API Java™ e HTTP
-
Predicati AEM supporto di requisiti di query comuni
-
API estensibile, che consente lo sviluppo di predicati query
-
JCR-SQL2 e XPath possono essere eseguiti direttamente tramite Sling e API JCR, restituendo risultati a Sling Risorse o Nodi JCR, rispettivamente.
Sling API
Apache Sling è il framework web RESTful alla base dell’AEM. Sling fornisce il routing delle richieste HTTP, modella i nodi JCR come risorse, fornisce il contesto di sicurezza e molto altro.
Sling Le API presentano il vantaggio aggiunto di essere create per l’estensione, il che significa che spesso è più semplice e sicuro incrementare il comportamento delle applicazioni create utilizzando Sling rispetto alle API JCR meno estensibili.
Utilizzi comuni di Sling API
-
Accesso ai nodi JCR come Sling Resources e l'accesso ai dati tramite ValueMaps.
-
Fornire contesto di sicurezza tramite ResourceResolver.
-
Creazione e rimozione di risorse tramite ResourceResolver metodi create/move/copy/delete (crea/sposta/copia/elimina).
-
Aggiornamento delle proprietà tramite ModifiableValueMap.
-
Elaborazione di blocchi predefiniti di richiesta
-
Elaborazione asincrona dei blocchi predefiniti
API JCR
Il API JCR (Java™ Content Repository) 2.0 fa parte di una specifica per le implementazioni JCR (nel caso dell’AEM, Apache Jackrabbit Oak). Tutta l’implementazione JCR deve essere conforme a e implementare queste API, e rappresenta quindi il livello più basso di API per interagire con i contenuti dell’AEM.
Il JCR stesso è un datastore NoSQL gerarchico/basato su struttura utilizzato dall’AEM come archivio dei contenuti. JCR dispone di una vasta gamma di API supportate, che vanno dal contenuto CRUD all’esecuzione di query sui contenuti. Nonostante questa robusta API, è raro che siano preferite rispetto al livello superiore AEM e Sling astrazioni.
Preferisci sempre le API JCR rispetto alle API Apache Jackrabbit Oak. Le API JCR sono per interazione con un archivio JCR, mentre le API Oak sono per implementazione un archivio JCR.
Concetti errati comuni sulle API JCR
Anche se JCR è un archivio di contenuti AEM, le sue API NON sono il metodo preferito per interagire con il contenuto. Preferisci invece le API AEM (Pagina, Risorse, Tag e così via) o le API Sling Resource in quanto forniscono astrazioni migliori.
Usi comuni delle API JCR
-
Osservazione JCR (ascolto degli eventi JCR)
-
Creazione di strutture di nodi profondi
API OSGi
Vi è poca sovrapposizione tra le API OSGi e le API di livello superiore (AEM, Slinge JCR) e la necessità di utilizzare le API OSGi è rara e richiede un elevato livello di esperienza nello sviluppo dell’AEM.
Confronto tra API OSGi e Apache Felix
OSGi definisce una specifica che tutti i contenitori OSGi devono implementare e rispettare. L’implementazione OSGi dell’AEM, Apache Felix, fornisce anche diverse API proprie.
- Preferisci API OSGi (
org.osgi
) sulle API Apache Felix (org.apache.felix
).
Utilizzi comuni delle API OSGi
-
Annotazioni OSGi per dichiarare servizi e componenti OSGi.
- Preferisci Annotazioni di OSGi Declarative Services (DS) 1.2 oltre Annotazioni Felix SCR per dichiarare servizi e componenti OSGi
-
API OSGi per l’inserimento dinamico nel codice annullamento/registrazione di servizi/componenti OSGi.
- Preferisci l’utilizzo delle annotazioni di OSGi DS 1.2 quando non è necessaria la gestione condizionale del servizio/componente OSGi (il che avviene il più delle volte).
Eccezioni alla regola
Di seguito sono riportate le eccezioni comuni alle regole definite in precedenza.
API OSGi
Quando si tratta di astrazioni OSGi di basso livello, come la definizione o la lettura delle proprietà dei componenti OSGi, le astrazioni più recenti fornite da org.osgi
sono preferite rispetto alle astrazioni Sling di livello superiore. Le astrazioni Sling concorrenti non sono state contrassegnate come @Deprecated
e suggerisci org.osgi
alternativa.
Inoltre, tieni presente che la definizione del nodo di configurazione OSGi preferisce cfg.json
oltre il sling:OsgiConfig
formato.
API di AEM Asset
-
Preferisci
com.day.cq.dam.api
oltrecom.adobe.granite.asset.api
.- Mentre il
com.day.cq
Le API Assets forniscono strumenti complementari per i casi d’uso della gestione delle risorse AEM. - Le API di Granite Assets supportano casi d’uso di basso livello per la gestione delle risorse (versione, relazioni).
- Mentre il
API di query
- AEM QueryBuilder non supporta alcune funzioni di query come suggerimenti, controllo ortografico e suggerimenti per l'indicizzazione, oltre ad altre funzioni meno comuni. Per eseguire query con queste funzioni è preferibile utilizzare JCR-SQL2.
Sling Registrazione servlet sling-servlet-registration
- Sling registrazione servlet, preferenza Annotazioni OSGi DS 1.2 con @SlingServletResourceTypes oltre
@SlingServlet
Sling Registrazione filtro sling-filter-registration
- Sling filtra la registrazione, preferisci Annotazioni OSGi DS 1.2 con @SlingServletFilter oltre
@SlingFilter
Frammenti di codice utili
Di seguito sono riportati snippet di codice Java™ utili che illustrano le best practice per i casi d’uso comuni utilizzando le API discusse. Questi snippet illustrano anche come passare dalle API meno preferite a quelle più preferite.
Sessione JCR a Sling ResourceResolver
ResourceResolver Sling con chiusura automatica
A partire dall'AEM 6.2, la Sling ResourceResolver è AutoClosable
in un try-with-resources dichiarazione. Utilizzando questa sintassi, una chiamata esplicita a resourceResolver .close()
non è necessario.
@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) { .. }
ResourceResolver Sling chiuso manualmente
ResourceResolvers può essere chiuso manualmente in un finally
se non è possibile utilizzare la tecnica di chiusura automatica illustrata sopra.
@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(); }
}
Percorso JCR per Sling Resource
Resource resource = ResourceResolver.getResource("/path/to/the/resource");
Nodo JCR a Sling Resource
Resource resource = resourceResolver.getResource(node.getPath());
Sling Resource a AEM Asset
Approccio consigliato
Il DamUtil.resolveToAsset(..)
funzione risolve qualsiasi risorsa sotto il dam:Asset
all’oggetto Asset spostandosi verso l’alto nella struttura, se necessario.
Asset asset = DamUtil.resolveToAsset(resource);
Approccio alternativo
L’adattamento di una risorsa a una risorsa richiede che la risorsa stessa sia la dam:Asset
nodo.
Asset asset = resource.adaptTo(Asset.class);
Sling Pagina Risorsa per AEM
Approccio consigliato
pageManager.getContainingPage(..)
risolve le risorse sotto cq:Page
all'oggetto Page spostandosi verso l'alto nella struttura, se necessario.
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
Page page = pageManager.getContainingPage(resource);
Page page2 = pageManager.getContainingPage("/content/path/to/page/jcr:content/or/component");
Approccio alternativo alternative-approach-1
L’adattamento di una risorsa a una pagina richiede che la risorsa stessa sia la cq:Page
nodo.
Page page = resource.adaptTo(Page.class);
Proprietà pagina Leggi AEM
Utilizzare i getter dell'oggetto Page per ottenere proprietà note (getTitle()
, getDescription()
e così via) e page.getProperties()
per ottenere [cq:Page]/jcr:content
ValueMap per recuperare altre proprietà.
Page page = resource.adaptTo(Page.class);
String title = page.getTitle();
Calendar value = page.getProperties().get("cq:lastModified", Calendar.getInstance());
Proprietà metadati risorse AEM lette
L’API Asset fornisce metodi pratici per leggere le proprietà da [dam:Asset]/jcr:content/metadata
nodo. Questo non è un ValueMap, il secondo parametro (valore predefinito e cast di tipo automatico) non è supportato.
Asset asset = resource.adaptTo(Asset.class);
String title = asset.getMetadataValue("dc:title");
Calendar lastModified = (Calendar) asset.getMetadata("cq:lastModified");
Letto Sling Resource proprietà read-sling-resource-properties
Quando le proprietà sono memorizzate in posizioni (proprietà o risorse relative) in cui le API AEM (Pagina, Risorsa) non possono accedere direttamente, il Sling È possibile utilizzare le risorse e ValueMaps per ottenere i dati.
ValueMap properties = resource.getValueMap();
String value = properties.get("jcr:title", "Default title");
String relativeResourceValue = properties.get("relative/propertyName", "Default value");
In questo caso, l’oggetto AEM potrebbe dover essere convertito in un Sling Resource per individuare in modo efficiente la proprietà o la risorsa secondaria desiderata.
Pagina AEM a Sling Resource
Resource resource = page.adaptTo(Resource.class);
Risorsa AEM a Sling Resource
Resource resource = asset.adaptTo(Resource.class);
Scrivi proprietà tramite SlingModifiableValueMap
Utilizzare Slingdi ModifiableValueMap per scrivere le proprietà nei nodi. Questo può scrivere solo nel nodo immediato (i percorsi di proprietà relativi non sono supportati).
Nota la chiamata a .adaptTo(ModifiableValueMap.class)
richiede autorizzazioni di scrittura per la risorsa, altrimenti restituisce null.
ModifiableValueMap properties = resource.adaptTo(ModifiableValueMap.class);
properties.put("newPropertyName", "new value");
properties.put("propertyNameToUpdate", "updated value");
properties.remove("propertyToRemove");
resource.getResourceResolver().commit();
Creare una pagina AEM
Utilizza sempre PageManager per creare pagine man mano che accetta un modello di pagina, necessario per definire e inizializzare correttamente le pagine in AEM.
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(); }
Creare un Sling Risorsa
ResourceResolver supporta operazioni di base per la creazione di risorse. Quando crei astrazioni di livello superiore (pagine AEM, risorse, tag e così via), utilizza i metodi forniti dai rispettivi manager.
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();
Eliminare un Sling Risorsa
ResourceResolver supporta la rimozione di una risorsa. Quando crei astrazioni di livello superiore (pagine AEM, risorse, tag e così via), utilizza i metodi forniti dai rispettivi manager.
resourceResolver.delete(resource);
resourceResolver.commit();