Práticas recomendadas da API Java™

O Adobe Experience Manager (AEM) é construído em uma pilha avançada de software de código aberto que expõe muitas APIs Java™ para uso durante o desenvolvimento. Este artigo explora as principais APIs e quando e por que elas devem ser usadas.

O AEM é construído em quatro conjuntos principais de APIs Java™.

  • Adobe Experience Manager (AEM)

    • Abstrações de produto, como páginas, ativos, fluxos de trabalho etc.
  • Apache Sling Web Framework

    • REST e abstrações baseadas em recursos, como recursos, mapas de valores e solicitações HTTP.
  • JCR (Apache Jackrabbit Oak)

    • Dados e abstrações de conteúdo, como nó, propriedades e sessões.
  • OSGi (Apache Felix)

    • Abstrações do contêiner de aplicativo OSGi, como serviços e componentes (OSGi).

Preferência da API Java™ "regra geral"

A regra geral é preferir as APIs/abstrações na seguinte ordem:

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

Se uma API for fornecida pelo AEM, prefira Sling, JCR e OSGi. Se o AEM não fornecer uma API, prefira Sling sobre JCR e OSGi.

Essa ordem é uma regra geral, o que significa que existem exceções. Os motivos aceitáveis para romper com essa regra são:

  • Exceções bem conhecidas, conforme descrito abaixo.

  • A funcionalidade necessária não está disponível em uma API de nível superior.

  • Operar no contexto de código existente (código de produto personalizado ou AEM) que usa uma API menos preferencial, e o custo de mover para a nova API é injustificável.

    • É melhor usar de forma consistente a API de nível inferior do que criar uma combinação.

APIs AEM

As APIs do AEM fornecem abstrações e funcionalidades específicas para casos de uso produzidos.

Por exemplo, AEM PageManager e Página As APIs fornecem abstrações para cq:Page nós no AEM que representam páginas da Web.

Enquanto esses nós estiverem disponíveis via Sling APIs como Recursos e APIs JCR como Nós, as APIs AEM fornecem abstrações para casos de uso comuns. Usar as APIs do AEM garante um comportamento consistente entre o AEM e as personalizações e extensões do AEM.

com.adobe.* vs com.day.* APIs

As APIs AEM têm uma preferência dentro do pacote, identificada pelos seguintes pacotes Java™, em ordem de preferência:

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

A variável com.adobe.cq O pacote aceita casos de uso de produtos, enquanto com.adobe.granite O oferece suporte a casos de uso de plataformas entre produtos, como fluxo de trabalho ou tarefas (que são usados em produtos: AEM Assets, Sites e assim por diante).

A variável com.day.cq O pacote contém APIs "originais". Essas APIs abordam abstrações e funcionalidades principais que existiam antes e/ou em torno da aquisição da Adobe Day CQ. Essas APIs são compatíveis e devem ser evitadas, a menos que com.adobe.cq ou com.adobe.granite O não fornece uma alternativa (mais recente).

Novas abstrações, como Content Fragments e Experience Fragments são criados no com.adobe.cq espaço em vez de com.day.cq descrito abaixo.

APIs de consulta

O AEM oferece suporte a vários idiomas de consulta. Os três idiomas principais são JCR-SQL2, XPath e Construtor de consulta AEM.

A preocupação mais importante é manter uma linguagem de consulta consistente em toda a base de código, para reduzir a complexidade e os custos de compreensão.

Todos os idiomas de consulta têm efetivamente os mesmos perfis de desempenho, como Apache Oak empilha-os em JCR-SQL2 para execução final de consulta, e o tempo de conversão para JCR-SQL2 é insignificante em comparação ao próprio tempo de consulta.

A API preferida é Construtor de consulta AEM, que é a abstração de mais alto nível e fornece uma API robusta para construção, execução e recuperação de resultados para consultas, e fornece o seguinte:

CAUTION
A API QueryBuilder do AEM vaza um objeto ResourceResolver. Para atenuar esse vazamento, siga este amostra de código.

Sling APIs

Apache Sling é a estrutura da Web RESTful que respalda o AEM. Sling O fornece roteamento de solicitações HTTP, nós JCR de modelos como recursos, fornece contexto de segurança e muito mais.

Sling As APIs têm a vantagem adicional de serem criadas para extensão, o que significa que geralmente é mais fácil e seguro aumentar o comportamento de aplicativos criados usando o Sling APIs do que as menos extensíveis APIs JCR.

Usos comuns do Sling APIs

APIs JCR

A variável APIs JCR (Java™ Content Repository) 2.0 é parte de uma especificação para implementações JCR (no caso de AEM, Apache Jackrabbit Oak). Toda implementação do JCR deve estar em conformidade com e implementar essas APIs e, portanto, é a API de nível mais baixo para interagir com o conteúdo do AEM.

O próprio JCR é um armazenamento de dados NoSQL hierárquico/em árvore que o AEM usa como seu repositório de conteúdo. O JCR tem uma grande variedade de APIs compatíveis, que vão desde a CRUD de conteúdo até a consulta de conteúdo. Apesar dessa API robusta, é raro que sejam preferidos em relação ao AEM de nível mais alto e Sling abstrações.

Sempre prefira as APIs JCR às APIs Apache Jackrabbit Oak. As APIs JCR são para interação com um repositório JCR, enquanto as APIs do Oak são para implementação um repositório JCR.

Equívocos comuns sobre APIs JCR

Embora o JCR seja um repositório de conteúdo AEM, suas APIs NÃO são o método preferido para interagir com o conteúdo. Em vez disso, prefira as APIs de AEM (Página, Ativos, Tag e assim por diante) ou as APIs de recurso do Sling, pois fornecem melhores abstrações.

CAUTION
O uso amplo das interfaces de nó e sessão das APIs JCR em um aplicativo AEM cheira a código. Assegurar Sling Em vez disso, as APIs devem ser usadas.

Usos comuns de APIs JCR

APIs OSGi

Há pouca sobreposição entre as APIs do OSGi e as APIs de nível superior (AEM, Slinge JCR), e a necessidade de usar APIs OSGi é rara e requer um alto nível de conhecimento em desenvolvimento de AEM.

OSGi versus APIs Apache Felix

O OSGi define uma especificação que todos os contêineres OSGi devem implementar e estar em conformidade. A implementação do AEM OSGi, Apache Felix, também fornece várias de suas próprias APIs.

  • Preferir APIs OSGi (org.osgi) sobre APIs Apache Felix (org.apache.felix).

Usos comuns de APIs OSGi

Exceções à regra

Veja a seguir exceções comuns às regras definidas acima.

APIs OSGi

Ao lidar com abstrações OSGi de baixo nível, como definir ou ler nas propriedades do componente OSGi, as abstrações mais recentes fornecidas pelo org.osgi são preferíveis sobre abstrações Sling de nível superior. As abstrações Sling concorrentes não foram marcadas como @Deprecated e sugerir a org.osgi alternativa.

Observe também que a definição do nó de configuração OSGi prefere cfg.json sobre o sling:OsgiConfig formato.

APIs de ativos AEM

  • Preferir com.day.cq.dam.api sobre com.adobe.granite.asset.api.

    • Embora a com.day.cq As APIs de ativos fornecem ferramentas mais complementares para casos de uso de gerenciamento de ativos do AEM.
    • As APIs do Granite Assets são compatíveis com casos de uso de gerenciamento de ativos de baixo nível (versão, relações).

APIs de consulta

  • O AEM QueryBuilder não é compatível com determinadas funções de consulta, como sugestões, verificação ortográfica e dicas de índice entre outras funções menos comuns. É preferível consultar com essas funções o JCR-SQL2.

Sling Registro de servlet sling-servlet-registration

Sling Filtrar registro sling-filter-registration

Trechos de código úteis

A seguir estão trechos de código Java™ úteis que ilustram as práticas recomendadas para casos de uso comuns usando APIs discutidas. Esses fragmentos também ilustram como mover de APIs menos preferenciais para APIs mais preferenciais.

Sessão JCR para Sling ResourceResolver

Fechamento automático do Sling ResourceResolver

Desde o AEM 6.2, a Sling ResourceResolver é AutoClosable em um try-with-resources declaração. Usando essa sintaxe, uma chamada explícita para resourceResolver .close() não é necessária.

@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 fechado manualmente

ResourceResolvers pode ser fechado manualmente em um finally se a técnica de fechamento automático mostrada acima não puder ser usada.

@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(); }
}

Caminho JCR para Sling Resource

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

Nó JCR para Sling Resource

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

Sling Resource para ativo AEM

Método recomendado

A variável DamUtil.resolveToAsset(..) resolve qualquer recurso na variável dam:Asset ao objeto de Ativo, subindo na árvore, conforme necessário.

Asset asset = DamUtil.resolveToAsset(resource);

Abordagem alternativa

Adaptar um recurso a um Ativo exige que o próprio recurso seja o dam:Asset nó.

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

Sling Recurso para página AEM

Método recomendado

pageManager.getContainingPage(..) resolve qualquer recurso no cq:Page ao objeto Page, subindo na árvore, conforme necessário.

PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
Page page = pageManager.getContainingPage(resource);
Page page2 = pageManager.getContainingPage("/content/path/to/page/jcr:content/or/component");

Abordagem alternativa alternative-approach-1

Adaptar um recurso a uma página exige que o próprio recurso seja o cq:Page nó.

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

Ler propriedades da página AEM

Use os getters do objeto Page para obter propriedades bem conhecidas (getTitle(), getDescription()e assim por diante) e page.getProperties() para obter a [cq:Page]/jcr:content ValueMap para recuperar outras propriedades.

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

Ler propriedades de metadados de ativos do AEM

A API de ativos fornece métodos convenientes para a leitura de propriedades da [dam:Asset]/jcr:content/metadata nó. Este não é um ValueMap, o segundo parâmetro (valor padrão e conversão de tipo automático) não é compatível.

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

Ler Sling Resource propriedades read-sling-resource-properties

Quando as propriedades são armazenadas em locais (propriedades ou recursos relativos) nos quais as APIs do AEM (Página, Ativo) não podem acessar diretamente, a variável Sling Resources e ValueMaps podem ser usados para obter os dados.

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

Nesse caso, o objeto AEM pode ter que ser convertido em um Sling Resource para localizar com eficiência a propriedade ou o sub-recurso desejado.

Página AEM para Sling Resource

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

Ativo AEM para Sling Resource

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

Gravar propriedades usando SlingModifiedValueMap de

Uso Slingdo ModisibleValueMap para gravar propriedades em nós. Isso só pode gravar no nó imediato (caminhos de propriedade relativos não são compatíveis).

Observe a chamada para .adaptTo(ModifiableValueMap.class) exige permissões de gravação para o recurso, caso contrário, retorna nulo.

ModifiableValueMap properties = resource.adaptTo(ModifiableValueMap.class);

properties.put("newPropertyName", "new value");
properties.put("propertyNameToUpdate", "updated value");
properties.remove("propertyToRemove");

resource.getResourceResolver().commit();

Criar uma página AEM

Sempre use o PageManager para criar páginas, pois ele precisa de um Modelo de página, é necessário para definir e inicializar páginas corretamente no 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(); }

Criar um Sling Recurso

O ResourceResolver dá suporte a operações básicas para a criação de recursos. Ao criar abstrações de nível superior (Páginas AEM, Ativos, Tags e assim por diante), use os métodos fornecidos pelos respectivos Gerentes.

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();

Excluir um Sling Recurso

ResourceResolver dá suporte à remoção de um recurso. Ao criar abstrações de nível superior (Páginas AEM, Ativos, Tags e assim por diante), use os métodos fornecidos pelos respectivos Gerentes.

resourceResolver.delete(resource);

resourceResolver.commit();
recommendation-more-help
c92bdb17-1e49-4e76-bcdd-89e4f85f45e6