Best practice per le API Java

Adobe Experience Manager (AEM) è basato su uno stack software open-source ricco che espone molte API Java da utilizzare durante lo sviluppo. Questo articolo esplora le API principali e spiega quando e perché dovrebbero essere utilizzate.

AEM è basato su 4 set API Java principali.

  • Adobe Experience Manager (AEM)

    • astrazioni di prodotto come pagine, risorse, flussi di lavoro, ecc.
  • Framework Web di Apache Sling

    • astrazioni REST e basate su risorse come risorse, mappe dei valori e richieste HTTP.
  • JCR (Apache Jackrabbit Oak)

    • astrazioni di dati e contenuti quali nodo, proprietà e sessioni.
  • OSGi (Apache Felix)

    • astrazioni del contenitore dell'applicazione OSGi quali servizi e componenti (OSGi).

Preferenza API Java "regola del pollice"

La regola generale è di preferire le API/astrazioni nel seguente ordine:

  1. AEM
  2. Sling
  3. JCR
  4. OSGi

Se un’API viene fornita da AEM, preferiscila rispetto a Sling, JCR e OSGi. Se AEM non fornisce un'API, preferisci Sling su JCR e OSGi.

Questo ordine è una regola generale, il che significa che esistono delle eccezioni. Motivi accettabili per uscire da questa regola sono i seguenti:

  • Eccezioni ben note, come descritto di seguito.

  • La funzionalità richiesta non è disponibile in un’API di livello superiore.

  • Operando nel contesto del codice esistente (codice di prodotto personalizzato o AEM) che utilizza un’API meno preferita e il costo per il passaggio alla nuova API non è giustificabile.

    • È meglio utilizzare in modo coerente l’API di livello inferiore rispetto a creare un mix.

API AEM

Le API 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.

Anche se questi nodi sono disponibili tramite Sling Le API as Resources e JCR API as Nodes AEM forniscono astrazioni per i casi d’uso comuni. L’utilizzo delle API AEM garantisce un comportamento coerente tra AEM prodotto e personalizzazioni ed estensioni a AEM.

com.adobe.* vs com.day.* API

AEM API hanno una preferenza intra-pacchetto, identificata dai seguenti pacchetti Java, in ordine di preferenza:

  1. com.adobe.cq
  2. com.adobe.granite
  3. com.day.cq

com.adobe.cq supporta i casi di utilizzo dei prodotti mentre com.adobe.granite supporta casi di utilizzo tra piattaforme, ad esempio flussi di lavoro o attività, utilizzati tra i prodotti: AEM Assets, Sites, ecc.).

com.day.cq contiene API "originali". Queste API riguardano le astrazioni e le funzionalità principali esistenti prima e/o intorno all’acquisizione di Adobe Day CQ. Queste API sono supportate e non devono essere evitate, a meno che com.adobe.cq o com.adobe.granite fornire un'alternativa (più recente).

Nuove astrazioni quali Content Fragments e Experience Fragments sono incorporati in com.adobe.cq spazio anziché com.day.cq descritto di seguito.

API di query

AEM supporta più linguaggi di query. Le tre lingue principali sono JCR-SQL2, XPath e Query Builder AEM.

La preoccupazione più importante è mantenere un linguaggio di query coerente all'interno della base di codice, per ridurre la complessità e i costi da comprendere.

Tutti i linguaggi di query hanno effettivamente gli stessi profili di prestazioni, come Apache Oak le trasferisce a JCR-SQL2 per l'esecuzione della query finale e il tempo di conversione a JCR-SQL2 è trascurabile rispetto al tempo di query stesso.

L’API preferita è Query Builder AEM, che rappresenta l’astrazione di livello più alto e fornisce un’API affidabile per la costruzione, l’esecuzione e il recupero dei risultati per le query, e fornisce quanto segue:

ATTENZIONE

AEM API QueryBuilder perde un oggetto ResourceResolver. Per attenuare questa perdita, segui questo esempio di codice.

Sling API

Apache Sling è il framework web RESTful su cui si fonda AEM. Sling fornisce routing delle richieste HTTP, modelli di nodi JCR come risorse, fornisce contesto di sicurezza e molto altro.

Sling Le API hanno il vantaggio aggiuntivo di essere create per l’estensione, il che significa che spesso è più facile e sicuro incrementare il comportamento delle applicazioni create utilizzando Sling API rispetto alle API JCR meno estensibili.

Uso comune di Sling API

API JCR

La API JCR (Java Content Repository) 2.0 fa parte di una specifica per le implementazioni JCR (nel caso di AEM, Apache Jackrabbit Oak). Tutte le implementazioni JCR devono essere conformi e implementate a queste API, ed è quindi l’API di livello più basso per interagire con i contenuti AEM.

Il JCR stesso è un datastore NoSQL gerarchico/basato su albero AEM utilizza come archivio dei contenuti. Il JCR dispone di una vasta gamma di API supportate, che vanno dal CRUD del contenuto alla query del contenuto. Nonostante questa solida 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 sbagliati comuni sulle API JCR

Anche se JCR è AEM archivio di contenuti, le sue API NON sono il metodo preferito per interagire con il contenuto. Preferiscono invece le API AEM (Pagina, Risorse, Tag, ecc.) o API di risorse Sling in quanto forniscono migliori astrazioni.

ATTENZIONE

L'ampio utilizzo delle interfacce Session e Node delle API JCR in un'applicazione AEM è un odore di codice. Assicurati Sling Le API non devono essere utilizzate al loro posto.

Utilizzo comune delle API JCR

API OSGi

C'è poca sovrapposizione tra le API OSGi e le API di livello superiore (AEM, Sling, e JCR), e la necessità di utilizzare le API OSGi è rara e richiede un alto livello di esperienza di sviluppo AEM.

API OSGi e Apache Felix

OSGi definisce una specifica a cui tutti i contenitori OSGi devono implementare e conformarsi. AEM implementazione OSGi, Apache Felix, fornisce anche diverse proprie API.

  • Preferisci le API OSGi (org.osgi) sulle API di Apache Felix (org.apache.felix).

Utilizzo comune delle API OSGi

Eccezioni alla regola

Di seguito sono riportate alcune eccezioni comuni alle regole definite in precedenza.

API OSGi

Quando si tratta di astrazioni OSGi di basso livello, come definire o leggere nelle proprietà dei componenti OSGi, le più recenti astrazioni fornite da org.osgi sono preferite rispetto alle astrazioni Sling di livello superiore. Le astrazioni Sling concorrenti non sono state contrassegnate come @Deprecated e suggeriscono org.osgi alternativa.

Nota anche che la definizione del nodo di configurazione OSGi preferisce cfg.json su sling:OsgiConfig formato.

API delle risorse AEM

  • Preferisci com.day.cq.dam.api over com.adobe.granite.asset.api.

    • Mentre il com.day.cq Le API di Assets forniscono strumenti più gratuiti per AEM casi d’uso di gestione delle risorse.
    • Le API di Granite Assets supportano casi d’uso per la gestione delle risorse di basso livello (versione, relazioni).

API di query

  • AEM QueryBuilder non supporta alcune funzioni di query come suggerimenti, controllo ortografico e suggerimenti di indice tra le altre funzioni meno comuni. Per eseguire query con queste funzioni è preferibile JCR-SQL2.

Sling Registrazione servlet

Sling Registrazione del filtro

Frammenti di codice utili

Di seguito sono riportati utili snippet di codice Java che illustrano le best practice per i casi d’uso comuni che utilizzano API discusse. Questi snippet illustrano anche come passare da API meno preferite a API più preferite.

Sessione JCR in Sling ResourceResolver

Chiusura automatica di Sling ResourceResolver

A partire dal AEM 6.2, il Sling ResourceResolver è AutoClosable in try-with-resources istruzione. Utilizzando questa sintassi, effettua 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) { .. }

Sling ResourceResolver chiuso manualmente

ResourceResolver può essere chiuso manualmente in un finally se non è possibile utilizzare la tecnica di chiusura automatica mostrata 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 su Sling Resource

Resource resource = ResourceResolver.getResource("/path/to/the/resource");

Nodo JCR su Sling Resource

Resource resource = resourceResolver.getResource(node.getPath());

Sling Resource AEM risorsa

Approccio consigliato

DamUtil.resolveToAsset(..)risolve qualsiasi risorsa in dam:Asset per accedere all’oggetto Asset, risalendo la struttura ad albero come necessario.

Asset asset = DamUtil.resolveToAsset(resource);

Approccio alternativo

L’adattamento di una risorsa a una risorsa richiede che la risorsa stessa sia dam:Asset nodo.

Asset asset = resource.adaptTo(Asset.class);

Sling Risorsa AEM pagina

Approccio consigliato

pageManager.getContainingPage(..) risolve qualsiasi risorsa in cq:Page all’oggetto Page, spostandosi verso l’alto nella struttura, in base alle esigenze.

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

L’adattamento di una risorsa a una pagina richiede che la risorsa stessa sia cq:Page nodo.

Page page = resource.adaptTo(Page.class);

Proprietà di lettura AEM pagina

Utilizzare i getters dell’oggetto Page per ottenere proprietà ben note (getTitle(), getDescription(), ecc.) e page.getProperties() per ottenere [cq:Page]/jcr:content ValueMap per il recupero di altre proprietà.

Page page = resource.adaptTo(Page.class);
String title = page.getTitle();
Calendar value = page.getProperties().get("cq:lastModified", Calendar.getInstance());

Leggere le proprietà dei metadati AEM risorsa

L’API delle risorse fornisce metodi utili per la lettura delle proprietà dalla [dam:Asset]/jcr:content/metadata nodo. Nota che non si tratta di un ValueMap, il secondo parametro (valore predefinito e casting automatico) non è supportato.

Asset asset = resource.adaptTo(Asset.class);
String title = asset.getMetadataValue("dc:title");
Calendar lastModified = (Calendar) asset.getMetadata("cq:lastModified");

Leggi Sling Resource proprietà

Quando le proprietà sono memorizzate in posizioni (proprietà o risorse relative) a cui non è possibile accedere direttamente dalle API AEM (Pagina, Risorsa), l’ Sling Per ottenere i dati è possibile utilizzare le risorse e ValueMaps .

ValueMap properties = resource.getValueMap();
String value = properties.get("jcr:title", "Default title");
String relativeResourceValue = properties.get("relative/propertyName", "Default value");

In questo caso, potrebbe essere necessario convertire l'oggetto AEM in un Sling Resource per individuare in modo efficiente la proprietà o la risorsa secondaria desiderata.

AEM pagina a Sling Resource

Resource resource = page.adaptTo(Resource.class);

AEM risorsa a Sling Resource

Resource resource = asset.adaptTo(Resource.class);

Proprietà di scrittura utilizzando Sling's ModificableValueMap

Utilizzo Slings ModificabileValueMap per scrivere proprietà sui nodi. Questo può solo scrivere sul nodo immediato (i percorsi delle proprietà relative 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

Utilizzare sempre PageManager per creare pagine in quanto richiede 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(); }

Crea un Sling Risorsa

ResourceResolver supporta operazioni di base per la creazione di risorse. Durante la creazione di astrazioni di livello superiore (pagine AEM, risorse, tag, ecc.) utilizzare i metodi forniti dai rispettivi responsabili.

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. Durante la creazione di astrazioni di livello superiore (pagine AEM, risorse, tag, ecc.) utilizzare i metodi forniti dai rispettivi responsabili.

resourceResolver.delete(resource);

resourceResolver.commit();

In questa pagina