Request to add Sling Nodetypes to AEM uber jar bundle manifests - adamcin/oakpal GitHub Wiki

What is Requested

AEM Developers working in Maven projects would benefit from having the full product CND embedded in the uber-jar artifacts released by Adobe (-apis, -obfuscated-apis, -unobfuscated-apis), linked by a Sling-Nodetypes header in each jar's MANIFEST.MF file.

Since the nodetypes in AEM are declared in many separate .cnd files within various packages and bundles, it would be acceptable to embed each of these files unmodified in the uber jars, and list them all in the Sling-Nodetypes header as separate, comma-separated paths. But since this may not account for sequential dependencies between CNDs, the ideal solution would be to embed a single monolithic CND file, like the one that is generated by the CRX/de Lite Tools -> Export Node Type feature, at a relative path within the bundle of SLING-INF/nodetypes.cnd.

The uber-jar-6.4.1-apis.jar file's META-INF/MANIFEST.MF file currently begins:

Manifest-Version: 1.0
Bundle-Description: The Adobe AEM Quickstart and Web Application.
Implementation-Title: cq-quickstart
Bundle-SymbolicName: com.day.cq.cq-quickstart-api
Implementation-Version: 6.4.0
Built-By: root
Bundle-ManifestVersion: 2
Bundle-Vendor: Adobe Systems ltd

Once the cnd is included in the jar file, you would add a Sling-Nodetypes header like so:

Manifest-Version: 1.0
Bundle-Description: The Adobe AEM Quickstart and Web Application.
Implementation-Title: cq-quickstart
Bundle-SymbolicName: com.day.cq.cq-quickstart-api
Implementation-Version: 6.4.0
Built-By: root
Bundle-ManifestVersion: 2
Bundle-Vendor: Adobe Systems ltd
Sling-Nodetypes: SLING-INF/nodetypes.cnd

While it is possible for members of the AEM community to publish their own jars with the exported nodetype, it is probably Adobe's prerogative to publish this artifact as a part of the officially licensed AEM APIs.

Relevant Use Cases

The Sling-Nodetypes header is a convention established for the Sling JCR Content Loader , so that bundles containing JCR content can avoid constraint violations when loading initial content without depending on the installation of additional artifacts over different channels, such as via filevault packages.

Even though the uber-jar artifacts are not intended for deployment in an AEM server or other OSGi environment, there are two main use-cases to support adopting this convention regardless, both related to testing JCR-dependent functionality during AEM project builds.

  1. Unit testing using Sling Mocks

The Sling Mocks unit testing library provides several ResourceResolver mock types. Two of these types (JCR_OAK and JCR_JACKRABBIT) support JCR nodetype registration by scanning the classpath for Manifests which declare a Sling-Nodetypes header, even though the mocks do not require execution within an OSGi framework.

The benefits for AEM developers in this regard would be 1) to allow testing of functionality which directly or indirectly depends on proprietary nodetypes like cq:Page and 2) to make it easier to test functionality which directly or indirectly depends on Sling nodetypes like sling:Folder, which may be provided by individual Sling bundles, but whose Java APIs are otherwise already included in whichever monolith uber-jar dependency is listed as a dependency on the provided- or test-scope classpath.

  1. Package validation using oakpal-maven-plugin

Because OakPAL constructs an Oak repository from scratch to simulate the installation of a content-package artifact, it must be provided, in one way or another, all the necessary JCR nodetypes to enforce the same schema constraints that are enforced in the production platform. The oakpal-maven-plugin has adopted the Sling Mocks pattern for classpath nodetype discovery using the Sling-Nodetypes header as one of the available methods for providing JCR nodetypes to install prior to observing a package installation in a transient Oak repository (see slingNodeTypes parameter). This would be the easiest method by far for AEM developers who already list one of the uber-jars as a dependency in their bundle modules. A minimal plugin declaration in a content-package module would look something like this:

<plugin>
  <groupId>net.adamcin.oakpal</groupId>
  <artifactId>oakpal-maven-plugin</artifactId>
  <version>1.1.6</version>
  <dependencies>
    <dependency>
      <groupId>com.adobe.aem</groupId>
      <artifactId>uber-jar</artifactId>
      <version>6.4.0</version>
      <classifier>apis</classifier>
    </dependency>
  </dependencies>
  <configuration>
    <slingNodeTypes>true</slingNodeTypes>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>scan</goal>
      </goals>
    </execution>
  </executions>
</plugin>
⚠️ **GitHub.com Fallback** ⚠️