Adobe Experience Manager(AEM) は、開発時に使用する多くの Java™ API を公開する、豊富なオープンソースソフトウェアスタックに基づいて構築されています。 この記事では、主な API、およびそれらを使用するタイミングと理由について説明します。
AEMは、4 つのプライマリ Java™ API セットを基に構築されています。
Adobe Experience Manager (AEM)
Apache Sling Web Framework
JCR(Apache Jackrabbit Oak)
OSGi(Apache Felix)
一般的なルールとして、次の順序で API/抽象を優先します。
AEMで API が提供されている場合は、より優先します。 Sling、JCR、OSGi の 3 つのリストが含まれます。 AEMに API がない場合は、 Sling JCR および OSGi 上で
この順序は一般的なルールで、例外が存在します。 このルールから解除する理由として許容できるものは次のとおりです。
以下に説明するよく知られた例外。
必要な機能は、上位レベルの API では使用できません。
それ自体であまり優先されない API を使用している既存のコード ( カスタムまたはAEM製品コード ) のコンテキストで動作し、新しい API に移行するためのコストは不当です。
AEM API は、製品化された使用例に固有の抽象概念と機能を提供します。
例: AEM PageManager および ページ API は以下の抽象概念を提供します。 cq:Page
web ページを表すAEMのノード。
これらのノードはで使用できますが、 Sling AEM API は、リソースとして API を、ノードとして JCR API を提供し、一般的な使用例の抽象概念を提供します。 AEM API を使用すると、AEMと製品の間で、カスタマイズとAEMの拡張の間で一貫した動作がおこなわれます。
AEM API は、パッケージ内の環境設定を持ち、次の Java™パッケージで識別されます。
com.adobe.cq
com.adobe.granite
com.day.cq
この com.adobe.cq
パッケージは製品の使用例をサポートしますが、 com.adobe.granite
は、ワークフローやタスクなど、製品をまたいだプラットフォームの使用例(製品全体で使用される)をサポートします。AEM Assets、Sites など )。
この com.day.cq
パッケージには「オリジナル」の API が含まれています。 これらの API は、Adobeが Day CQ. これらの API はサポートされており、 com.adobe.cq
または com.adobe.granite
パッケージには、新しい代替手段は用意されていません。
次のような新しい抽象概念 Content Fragments および Experience Fragments は com.adobe.cq
~ではなく空間 com.day.cq
以下に説明します。
AEMは複数のクエリ言語をサポートしています。 主に次の 3 つの言語があります。 JCR-SQL2、XPath および AEM Query Builder.
最も重要な問題は、コードベース全体で一貫性のあるクエリ言語を維持し、理解するための複雑さとコストを軽減することです。
すべてのクエリ言語は、 Apache Oak 最終的なクエリ実行のために JCR-SQL2 にトランスパイルします。JCR-SQL2 への変換時間は、クエリ時間自体に比べて非常に短い時間です。
推奨される API は次のとおりです。 AEM Query Builder:最高レベルの抽象化で、クエリの結果を構築、実行および取得するための堅牢な API を提供し、次の機能を提供します。
単純なパラメータ化されたクエリ構造(Map としてモデル化されたクエリパラメータ)
ネイティブ Java™ API と HTTP API
AEM述語 共通のクエリ要件のサポート
拡張可能な API (カスタムの開発に使用) クエリ述語
JCR-SQL2 および XPath は、 Sling および JCR API、結果を返す Sling リソース または JCR ノード、それぞれ。
AEM QueryBuilder API は、ResourceResolver オブジェクトをリークします。 この漏れを軽減するには、次の手順に従います コードサンプル.
Apache Sling は、AEMを支える RESTful Web フレームワークです。 Sling は、HTTP リクエストルーティングを提供し、JCR ノードをリソースとしてモデル化し、セキュリティコンテキストなどを提供します。
Sling API には拡張機能向けにビルドされるというメリットが追加されています。つまり、を使用してビルドされたアプリケーションの動作を容易かつ安全に拡張できます。 Sling 拡張性の低い JCR API よりも API が多い。
JCR ノードへのアクセス Sling Resources を使用し、 ValueMaps.
を介したセキュリティコンテキストの提供 ResourceResolver.
ResourceResolver の メソッドの作成/移動/コピー/削除.
を使用したプロパティの更新 ModifiableValueMap.
構築リクエスト処理構築ブロック
非同期作業処理の構築ブロック
この JCR(Java™ Content Repository)2.0 API は、JCR 実装の仕様の一部です (AEMの場合、 Apache Jackrabbit Oak) をクリックします。 すべての JCR 実装は、これらの API に準拠し実装する必要があります。したがって、AEMコンテンツを操作するための最も低レベルの API です。
JCR 自体は、階層/ツリーベースの NoSQL データストアAEMで、がコンテンツリポジトリとして使用します。 JCR には、コンテンツ CRUD からコンテンツのクエリまで、様々なサポートされている API が多数あります。 この堅牢な API にもかかわらず、上位レベルのAEMや Sling 抽象概念
Apache Jackrabbit Oak API よりも JCR API を常に優先します。 JCR API は、 対話 JCR リポジトリを使用し、Oak API は 実装 JCR リポジトリ。
JCR はAEMコンテンツリポジトリですが、API はコンテンツを操作する際の推奨される方法ではありません。 より優れた抽象概念を提供するので、代わりにAEM API(Page、Assets、Tag など)または Sling Resource API を優先します。
AEMアプリケーションでの JCR API のセッションおよびノードインターフェイスの幅広い使用は、コードスメルです。 確認 Sling 代わりに API を使用する必要があります。
JCR の監視(JCR イベントのリッスン)
ディープノード構造の作成
OSGi API と上位レベルの API(AEM、 Sling、 、JCR など )、および OSGi API を使用する必要はまれで、高いレベルのAEM開発専門知識が必要です。
OSGi は、すべての OSGi コンテナが実装し、準拠する必要がある仕様を定義します。 AEM OSGi 実装の Apache Felix は、独自の API もいくつか提供しています。
org.osgi
) を Apache Felix API 経由 (org.apache.felix
) をクリックします。OSGi サービスおよびコンポーネントの宣言用の OSGi 注釈。
動的なインコード用の OSGi API OSGi サービス/コンポーネントの登録/解除.
次に、上記の規則に対する一般的な例外を示します。
OSGi コンポーネントプロパティでの定義や読み取りなど、低レベルの OSGi 抽象概念を扱う場合、次の方法で提供される新しい抽象概念 org.osgi
は、上位レベルの Sling の抽象概念よりも優先されます。 競合する Sling の抽象概念は、 @Deprecated
そして、 org.osgi
代替案。
また、OSGi 設定ノードの定義の方が優先される点にも注意してください。 cfg.json
を sling:OsgiConfig
形式
優先 com.day.cq.dam.api
over com.adobe.granite.asset.api
.
com.day.cq
Assets API には、AEM Asset Management のユースケース向けのより包括的なツールが用意されています。@SlingServlet
@SlingFilter
以下は、議論された API を使用する一般的な使用例のベストプラクティスを説明する Java™コードスニペットです。 また、これらのスニペットでは、優先度の低い API からより優先度の高い API に移行する方法を説明しています。
AEM 6.2 以降、 Sling ResourceResolver は AutoClosable
内 try-with-resources 文。 この構文を使用すると、 resourceResolver .close()
は不要です。
@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 は、 finally
ブロック内に含める必要があります。
@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(..)
関数は、 dam:Asset
必要に応じてツリーを上に移動して、Asset オブジェクトに移動します。
Asset asset = DamUtil.resolveToAsset(resource);
リソースをアセットに適応させるには、リソース自体が dam:Asset
ノード。
Asset asset = resource.adaptTo(Asset.class);
pageManager.getContainingPage(..)
下のリソースを解決します。 cq:Page
必要に応じてツリーの上に移動し、ページオブジェクトに移動します。
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
Page page = pageManager.getContainingPage(resource);
Page page2 = pageManager.getContainingPage("/content/path/to/page/jcr:content/or/component");
リソースをページに適応させるには、リソース自体が cq:Page
ノード。
Page page = resource.adaptTo(Page.class);
Page オブジェクトの getter を使用して、よく知られているプロパティ (getTitle()
, getDescription()
など )、および page.getProperties()
を取得する [cq:Page]/jcr:content
他のプロパティを取得するための ValueMap。
Page page = resource.adaptTo(Page.class);
String title = page.getTitle();
Calendar value = page.getProperties().get("cq:lastModified", Calendar.getInstance());
Asset API には、 [dam:Asset]/jcr:content/metadata
ノード。 これは ValueMap ではなく、2 番目のパラメータ(デフォルト値、自動タイプキャスト)はサポートされていません。
Asset asset = resource.adaptTo(Asset.class);
String title = asset.getMetadataValue("dc:title");
Calendar lastModified = (Calendar) asset.getMetadata("cq:lastModified");
AEM API(ページ、アセット)が直接アクセスできない場所(プロパティまたは相対リソース)にプロパティが保存されている場合、 Sling データの取得には、リソースと値マップを使用できます。
ValueMap properties = resource.getValueMap();
String value = properties.get("jcr:title", "Default title");
String relativeResourceValue = properties.get("relative/propertyName", "Default value");
この場合、AEMオブジェクトを Sling Resource 目的のプロパティまたはサブリソースを効率的に見つけ出す。
Resource resource = page.adaptTo(Resource.class);
Resource resource = asset.adaptTo(Resource.class);
用途 Sling's ModifiableValueMap ノードにプロパティを書き込みます。 これは、即時ノードにのみ書き込むことができます(相対プロパティパスはサポートされていません)。
への呼び出しに注意してください。 .adaptTo(ModifiableValueMap.class)
にはリソースへの書き込み権限が必要です。権限がない場合は null が返されます。
ModifiableValueMap properties = resource.adaptTo(ModifiableValueMap.class);
properties.put("newPropertyName", "new value");
properties.put("propertyNameToUpdate", "updated value");
properties.remove("propertyToRemove");
resource.getResourceResolver().commit();
AEMでページを適切に定義および初期化するには、ページテンプレートを取るページを作成する場合は、必ず PageManager を使用してください。
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 は、リソースを作成するための基本的な操作をサポートします。 上位レベルの抽象概念 (AEM Pages、Assets、タグなど ) を作成する場合は、それぞれのマネージャーが提供するメソッドを使用します。
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 は、リソースの削除をサポートします。 上位レベルの抽象概念 (AEM Pages、Assets、タグなど ) を作成する場合は、それぞれのマネージャーが提供するメソッドを使用します。
resourceResolver.delete(resource);
resourceResolver.commit();