Study guide
6.1 Maven Project Structure & AEM Project Archetype
Adobe Certified Professional - AEM Sites Developer AD0-E128
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Dispatcher Farm & Multi-Site Configuration
1.1 AEM Dispatcher Configuration & Caching Fundamentals 1.2 Multi-Site Management (MSM) & Blueprint/Live Copy Architecture 1.3 OSGi Configuration Management & Run Modes (.cfg.json)
2 Chapter 2: Oak Indexing & Custom Logging
2.1 Custom Oak Index Definitions & Lucene Query Optimization 2.2 AEM Custom Logging, Logback Configurations & Request Tracing
3 Chapter 3: Component Architecture, HTL & Client Libraries
3.1 Core Components & Proxy Component Pattern 3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping 3.3 Client-Side Libraries (Clientlibs) Architecture & Management
4 Chapter 4: Sling Models & OSGi Declarative Services
4.1 Sling Models Framework, Injectors & Model Exporter 4.2 OSGi Declarative Services, Component Lifecycle & Service Rankings
5 Chapter 5: Templates, Fragments & Business Workflows
5.1 Editable Templates, Structure, Initial Content & Content Policies 5.2 Content Fragments, Experience Fragments & Headless Delivery 5.3 AEM Workflows, Custom Process Steps & Launchers
6 Chapter 6: Build, Packaging & Cloud Manager CI/CD
6.1 Maven Project Structure & AEM Project Archetype 6.2 Content Package Types, Packaging Rules & FileVault Validation 6.3 Cloud Manager CI/CD Pipelines & Quality Gates 6.4 Rapid Development Environments (RDE) & Sling Repoinit Scripts
7 Chapter 7: Environment Maintenance & Content Distribution
7.1 AEM Maintenance Releases & Cloud Service Version Updates 7.2 AEM Deployment Topologies & Cloud Architecture 7.3 Replication Agents & Sling Content Distribution 7.4 Repository Maintenance: Revision Cleanup, Compaction & Purge Tasks
8 Chapter 8: Analyzing, Debugging & Diagnostic Tools
8.1 System Log Analysis & Diagnostic Tooling 8.2 Debugging Client-Side Libraries & Granite Dumplibs 8.3 Dispatcher Caching Diagnostics, X-Cache-Info & Local Validation 8.4 Environment Troubleshooting, Web Console & Developer Console
6.1 Maven Project Structure & AEM Project Archetype
Key Takeaways Explain This Topic AI
The AEM Project Archetype generates a standardized multi-module Maven reactor project separating concerns across OSGi Java bundles, immutable application code, mutable content, OSGi configurations, and frontend assets.
The core module compiles into a standard OSGi bundle JAR containing backend business logic, Sling Models, OSGi Declarative Services, Servlets, and repoinit-invoking jobs.
The ui.apps module packages immutable customer application code under /apps with package type application; custom projects must not place code under the product-owned /libs tree.
The all module serves exclusively as a container aggregator using the filevault-package-maven-plugin to embed core, ui.apps, ui.config, and ui.content into a single deployable artifact for Cloud Manager.
In AEM as a Cloud Service, OSGi configurations are decoupled from ui.apps into a dedicated ui.config module using .cfg.json syntax and targeted runmode folders.
Last updated: September 2026
6.1 Maven Project Structure & AEM Project Archetype
Quick Answer: The AEM Project Archetype generates a multi-module Maven reactor where the all module aggregates subpackages, core compiles the OSGi Java bundle, ui.apps packages immutable code under /apps , ui.config stores OSGi configurations in .cfg.json format, ui.content manages mutable authorable content ( /content , /conf ), ui.frontend compiles modern client-side assets via Webpack, and dispatcher packages Apache/Dispatcher web-tier configs. The reactor root pom.xml manages dependencies using <scope>provided</scope> for the Cloud Service SDK ( aem-sdk-api ).
Enterprise implementations of Adobe Experience Manager (AEM) require robust build automation capable of orchestrating diverse technologies: Java OSGi bundles, Apache Jackrabbit FileVault JCR content packages, modern front-end build pipelines (TypeScript, Webpack, Sass), and Apache HTTP Server/Dispatcher configurations. To standardize project structures across the global ecosystem, Adobe maintains the AEM Project Archetype ( com.adobe.aem:aem-project-archetype ).
Adhering to the archetype conventions is not merely a stylistic recommendation; it is an architectural prerequisite for building, testing, and deploying solutions via Adobe Cloud Manager for both AEM as a Cloud Service (AEMaaCS) and AEM 6.5.
The Multi-Module Reactor Architecture
A modern AEM codebase uses a Maven multi-module reactor. Rather than building a single monolithic archive, Maven executes a top-down build managed by a root pom.xml with <packaging>pom</packaging> . The root POM defines compilation order, orchestrates plugin execution, and manages shared dependency versions. my-project/
- ├── pom.xml <-- Root Reactor POM
- ├── core/ <-- OSGi Bundle (Java, Sling Models, Servlets)
- │ └── pom.xml
- ├── ui.apps/ <-- Immutable Application Code (/apps)
- │ └── pom.xml
- ├── ui.config/ <-- OSGi Configurations (/apps/.../osgiconfig)
- │ └── pom.xml
- ├── ui.content/ <-- Mutable Content & Editable Templates (/content, /conf)
- │ └── pom.xml
- ├── ui.frontend/ <-- Webpack / Front-End Build Pipeline
- │ ├── package.json
- │ └── pom.xml
- ├── all/ <-- Pure Container Aggregator Package
- │ └── pom.xml
- └── dispatcher/ <-- Apache HTTPD and Dispatcher Configurations
- └── src/
- Module Responsibilities & Target Artifact Matrix
Module Packaging Type Artifact Output Target Deployment Location Primary Contents
core jar / bundle OSGi Bundle JAR Embedded into all ( /apps/<app>/install ) Java source code, Sling Models, OSGi Declarative Services, Sling Servlets, Workflow steps, Event Listeners.
ui.apps content-package Application Content Package /apps (customer application code on the immutable mount) HTL component scripts, Granite UI dialogs ( cq:dialog ), component clientlibs, rendering templates.
ui.config content-package Application Content Package /apps/<app>/osgiconfig OSGi .cfg.json configurations organized by runmode folders ( config , config.author , config.publish ).
ui.content content-package Content Package /content , /conf , /content/dam (Mutable) Editable template structures, Content policies, DAM asset folders, Initial site navigation structures.
ui.frontend pom Clientlib Directory (Static CSS/JS) Copied into ui.apps clientlibs Webpack/Vite configs, TypeScript, SCSS, ESLint, Node.js dependencies ( package.json ).
all content-package Container Content Package Cloud Manager CI/CD Target Embeds core , ui.apps , ui.config , and ui.content . No raw content of its own.
dispatcher pom Deployment Archive ( .tar.gz ) Dispatcher web tier (Apache HTTPD) Virtual host files ( *.vhost ), Farm files ( *.farm ), Rewrite rules, Filter configurations.
- Deep Dive: Submodule Roles & Boundaries
- 1. core Module: OSGi Java Bundle
The core module contains all backend Java code. It compiles using the bnd-maven-plugin (or the legacy maven-bundle-plugin ) to produce an OSGi R7 compliant bundle JAR containing an OSGi manifest ( MANIFEST.MF ) with generated Export-Package and Import-Package headers.
Key responsibilities include:
Sling Models : Component backend adapters annotated with @Model utilizing @ValueMapValue , @ChildResource , and @Self .
OSGi Services & Components : Business logic annotated with OSGi Declarative Services annotations ( @Component , @Reference , @Activate , @Modified ).
Sling Servlets : REST endpoints bound via @Component(service = Servlet.class) using sling.servlet.paths or sling.servlet.resourceTypes .
Unit Tests : Mock-driven unit testing using JUnit 5, Mockito, and the io.wcm.testing.aem-mock.junit5 library.
Exam Trap: The core module must never contain HTL scripts, dialog XML, or client-side assets. Furthermore, it should never directly manipulate repository content upon bundle activation using administrative sessions ( loginAdministrative ); all initial data setup must be delegated to Sling Repoinit.
2. ui.apps Module: Immutable Application Code
The ui.apps module packages the frontend component scripts, dialog definitions, and client library structures. Under AEM as a Cloud Service, customer code from ui.apps deploys to the immutable application area under /apps ; /libs is product-owned and must not contain custom code.
Key contents include:
Component definitions: /apps/<app>/components/structure , /apps/<app>/components/content .
HTL rendering scripts: component.html , template partials.
Granite UI component dialogs: _cq_dialog/.content.xml defining authoring touchpoints.
Client-side libraries: /apps/<app>/clientlibs containing CSS, JS, and font assets produced by ui.frontend .
In ui.apps/pom.xml , the package type is explicitly declared as application via the filevault-package-maven-plugin : <plugin>
- <groupId>org.apache.jackrabbit</groupId>
- <artifactId>filevault-package-maven-plugin</artifactId>
- <configuration>
- <packageType>application</packageType>
- <repositoryStructurePackages>
- <repositoryStructurePackage>
- <groupId>com.mycompany.myproject</groupId>
- <artifactId>myproject.ui.apps.structure</artifactId>
- </repositoryStructurePackage>
- </repositoryStructurePackages>
- </configuration>
- </plugin>
- 3. ui.config Module: Dedicated OSGi Configuration
In earlier archetype versions, OSGi configurations resided inside ui.apps . Modern AEM Project Archetypes isolate all OSGi configurations into a dedicated ui.config module.
Why this separation exists:
Configuration Lifecycle : OSGi configurations undergo different governance and deployment checks than component templates and HTL scripts.
Package Purity : Keeps ui.apps focused purely on component code, while ui.config manages runmode-specific settings in /apps/<app>/osgiconfig .
Configuration Format : Enforces the modern Apache Sling OSGi configuration JSON format ( .cfg.json ) instead of legacy .config or .xml formats. ui.config/src/main/content/jcr_root/apps/myproject/osgiconfig/
- ├── config/ <-- All environments
- │ └── org.apache.sling.commons.log.LogManager.factory.config~myproject.cfg.json
- ├── config.author/ <-- Author runmode only
- │ └── com.mycompany.core.services.AuthorService.cfg.json
- ├── config.publish/ <-- Publish runmode only
- │ └── com.mycompany.core.services.PublishService.cfg.json
- ├── config.stage/ <-- Staging environment only
- └── config.prod/ <-- Production environment only
- 4. ui.content Module: Mutable Runtime Content
The ui.content module packages nodes that live in the mutable Oak repository mount . This includes:
Editable Templates & Policies : Stored under /conf/<app>/settings/wcm/templates and /conf/<app>/settings/wcm/policies .
DAM Asset Folders : Initial asset folder metadata under /content/dam/<app> .
Site Structure : Baseline site nodes under /content/<app> .
Experience Fragments : Template structures under /content/experience-fragments/<app> .
The ui.content/pom.xml explicitly defines <packageType>content</packageType> . Filter rules in filter.xml must use safe import modes ( mode="merge" or mode="update" ) to prevent overwriting author-created pages and policies in production environments.
5. ui.frontend Module: Modern Client-Side Tooling
Rather than forcing front-end developers to write raw ES5 JavaScript inside CRXDE Lite, the ui.frontend module provides an isolated, modern front-end environment with Webpack, Babel, TypeScript, PostCSS, and Sass.
Compilation lifecycle:
The Maven build delegates to frontend-maven-plugin .
The plugin downloads node.js and npm into the local working directory (no global installation required).
It executes npm install and npm run build (or npm run prod ).
Webpack bundles the compiled minified CSS, JS, and source maps directly into the ui.apps source directory at ui.apps/src/main/content/jcr_root/apps/<app>/clientlibs/clientlib-site .
When Maven subsequently builds ui.apps , the generated clientlib is bundled into the application package.
6. all Module: The Container Aggregator
The all module produces a single container package ( <packageType>container</packageType> ). It does not contain any JCR content, HTL, or Java files. Instead, its sole purpose is to embed all other compiled artifacts into a single installable package for Cloud Manager.
- In all/pom.xml , the filevault-package-maven-plugin embeds the subpackages and OSGi bundle: <plugin>
- <groupId>org.apache.jackrabbit</groupId>
- <artifactId>filevault-package-maven-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <packageType>container</packageType>
- <embeddeds>
- <!-- Embed Java OSGi Bundle -->
- <embedded>
- <groupId>com.mycompany.myproject</groupId>
- <artifactId>myproject.core</artifactId>
- <target>/apps/myproject-packages/application/install</target>
- </embedded>
- <!-- Embed ui.apps Package -->
- <embedded>
- <groupId>com.mycompany.myproject</groupId>
- <artifactId>myproject.ui.apps</artifactId>
- <type>zip</type>
- <target>/apps/myproject-packages/application/install</target>
- </embedded>
- <!-- Embed ui.config Package -->
- <embedded>
- <groupId>com.mycompany.myproject</groupId>
- <artifactId>myproject.ui.config</artifactId>
- <type>zip</type>
- <target>/apps/myproject-packages/application/install</target>
- </embedded>
- <!-- Embed ui.content Package -->
- <embedded>
- <groupId>com.mycompany.myproject</groupId>
- <artifactId>myproject.ui.content</artifactId>
- <type>zip</type>
- <target>/apps/myproject-packages/content/install</target>
- </embedded>
- </embeddeds>
- </configuration>
- </plugin>
Exam Rule: Notice the target install paths in the container package:
Application packages and OSGi bundles ( ui.apps , ui.config , core ) target /apps/<app>-packages/application/install .
Content packages ( ui.content ) target /apps/<app>-packages/content/install .
Cloud Manager uses these distinct install paths to sequence installation between immutable and mutable storage mounts.
7. dispatcher Module: Web Tier Configurations
The dispatcher module houses Apache HTTP Server configurations ( httpd.conf , conf.d/*.conf ) and Dispatcher configurations ( conf.dispatcher.d/*.farm , rules.any , filters.any ).
In AEM as a Cloud Service, Dispatcher files are validated during the build using the Dispatcher Validator ( bin/validate.sh ) provided in the AEM SDK Dispatcher Tools. Cloud Manager packages the validated configuration directory into a .tar.gz archive and deploys it directly to the managed Apache/Dispatcher Docker containers.
Root Reactor POM: Dependency & Plugin Management
The root pom.xml orchestrates the entire multi-module reactor. It defines module order, sets common Java compiler versions (Java 11 or 17), and controls dependency resolution through <dependencyManagement> and <pluginManagement> .
Dependency Management & aem-sdk-api
In modern AEMaaCS projects, custom bundles compile against the unified aem-sdk-api artifact. This replaces the legacy monolithic uber-jar from AEM 6.x. <dependencyManagement>
- <dependencies>
- <!-- AEM as a Cloud Service SDK API -->
- <dependency>
- <groupId>com.adobe.aem</groupId>
- <artifactId>aem-sdk-api</artifactId>
- <version>${aem.sdk.api.version}</version>
- <scope>provided</scope>
- </dependency>
- <!-- Core Components Dependency -->
- <dependency>
- <groupId>com.adobe.cq</groupId>
- <artifactId>core.wcm.components.core</artifactId>
- <version>${core.wcm.components.version}</version>
- </dependency>
- <!-- Testing Dependencies -->
- <dependency>
- <groupId>org.junit</groupId>
- <artifactId>junit-bom</artifactId>
- <version>5.9.3</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- Maven Scopes in AEM Development
Scope Meaning in AEM Architecture Examples
provided The dependency is required for compilation but must not be packaged into the bundle JAR because the AEM OSGi runtime container already exports it at runtime. aem-sdk-api , org.osgi.service.component.annotations , javax.servlet-api .
compile The dependency is bundled or resolved as part of the compilation classpath. Third-party utility libraries (e.g., Apache Commons Text) marked compile must be embedded into the bundle using bnd instructions. Custom utility libraries, domain SDKs.
test Required only for compiling and executing unit test suites; omitted from all production artifacts. junit-jupiter , mockito-core , io.wcm.testing.aem-mock.junit5 .
Exam Trap: Marking aem-sdk-api with <scope>compile</scope> instead of <scope>provided</scope> is a catastrophic error. Maven will attempt to package hundreds of megabytes of AEM internal platform classes into your OSGi bundle, triggering severe classpath collisions, ClassCastException failures, and OSGi bundle resolution errors upon deployment.