6.4 Rapid Development Environments (RDE) & Sling Repoinit Scripts
Key Takeaways
- Rapid Development Environments let a developer deploy supported code, content, and Dispatcher configuration directly with the Adobe I/O RDE CLI for rapid cloud validation; Adobe does not promise a fixed seconds-per-deployment SLA.
- Repoinit runs when its RepositoryInitializer OSGi configuration is registered and performs explicit atomic startup operations; scripts cannot assume application package paths already exist because packages are installed afterward.
- For Cloud Service provisioning of service users, groups, paths, and ACLs, Adobe recommends explicit repoinit scripts rather than packaging protected user content.
- Repoinit statements support declarative creation of service users, assignment of fine-grained JCR privileges, creation of intermediate folder structures, and registration of custom namespaces and nodetypes.
- OSGi service users authenticate programmatically without administrative credentials via Service User Mappings (ServiceUserMapperImpl.amended) linked to specific bundle symbolic names and subservices.
6.4 Rapid Development Environments (RDE) & Sling Repoinit Scripts
Quick Answer: Rapid Development Environments (RDE) allow developers to deploy individual OSGi bundles, content packages, and frontend scripts directly to a cloud-hosted development environment for rapid feedback using the Adobe I/O CLI (
aio aem:rde:install), without running a full Cloud Manager pipeline for each iteration. Concurrently, Sling Repository Initialization (repoinit) scripts run at early startup to create system users, configure ACLs, and build folder hierarchies deterministically. In AEM as a Cloud Service, system users and ACLs should be provisioned with repoinit rather than protected user-content packages, and accessed programmatically viaServiceUserMapperImpl.amended.
Developing for AEM as a Cloud Service requires tools that balance cloud architectural parity with rapid developer feedback loops. Historically, verifying code in a real cloud environment required committing to Git and executing a full Cloud Manager pipeline—a much longer feedback cycle than a targeted RDE deployment.
To solve this, Adobe introduced Rapid Development Environments (RDE). Paired with Sling Repository Initialization (repoinit), developers gain both near-instantaneous cloud deployment capabilities and rock-solid, declarative repository setup.
Rapid Development Environments (RDE): Purpose & Workflow
An RDE is a dedicated, single-tenant cloud environment provisioned within an Adobe Cloud Manager program. Unlike standard Development environments that require formal Git commits and full pipeline orchestration, an RDE allows developers to push changes directly from their local terminal to the cloud runtime through the RDE CLI without a fixed documented completion-time guarantee.
Environment Comparison Matrix
| Capability | Local AEM SDK | Rapid Development Environment (RDE) | Cloud Manager Pipeline (Dev/Stage/Prod) |
|---|---|---|---|
| Deployment Path | Local Maven or IDE workflow | Direct RDE CLI deployment | Governed Git and Cloud Manager pipeline |
| Cloud Architecture | Single local Quickstart JVM | True Cloud Architecture (Author, Publish, Dispatcher containers) | Full multi-tier production-grade cloud cluster |
| Adobe IMS Integration | Simulated / Mocked | Live Adobe IMS enterprise authentication | Live Adobe IMS enterprise authentication |
| Asset Compute Service | Mocked locally | Real Cloud Microservices | Real Cloud Microservices |
| Deployment Tool | mvn -PautoInstallPackage / CRXDE | aio aem:rde (Adobe I/O CLI) | Git commit triggered Cloud Manager Pipeline |
| Primary Use Case | Rapid local component authoring | Validating integrations, cloud security, and cloud replication | Formal verification, staging, and production release |
Adobe I/O AEM CLI (aio aem:rde) Command Reference
Developers interact with RDEs using the Adobe I/O Extensible CLI (aio) equipped with the @adobe/aio-cli-plugin-aem-rde plugin.
Core RDE CLI Commands
# 1. Install an OSGi Bundle directly to RDE
aio aem:rde:install target/myproject.core-1.0.0-SNAPSHOT.jar
# 2. Install a Content Package (ui.apps or ui.content)
aio aem:rde:install target/myproject.ui.apps-1.0.0-SNAPSHOT.zip
# 3. Install an individual OSGi configuration file
aio aem:rde:install src/main/content/jcr_root/apps/myproject/osgiconfig/config/com.mycompany.service.cfg.json
# 4. Install an individual HTL script or clientlib file directly
aio aem:rde:install src/main/content/jcr_root/apps/myproject/components/hero/hero.html -t content-file -p /apps/myproject/components/hero/hero.html
# 5. Check the status of deployed artifacts and OSGi bundle states
aio aem:rde:status
# 6. View deployment logs and history
aio aem:rde:history
# 7. Reset the RDE to its clean, initial baseline state
aio aem:rde:reset
The aio aem:rde:reset Command
During rapid experimentation, an RDE may accumulate test content, conflicting packages, or dirty repository states. The aio aem:rde:reset command cycles the environment, clears RDE state, and brings it to the most recently available AEM version. Preserve anything needed before reset and redeploy the project afterward. This eliminates the need to manually delete packages or reconstruct JCR nodes.
Sling Repository Initialization (Repoinit)
In legacy AEM versions, developers packaged system users and access control lists (ACLs) directly into ui.content packages as raw .content.xml files under /home/users/system. In AEM as a Cloud Service, this approach is completely prohibited:
- Installation Lifecycle: Content packages are installed late in the startup sequence, well after OSGi bundles have activated. If an OSGi service starts up and requests a
ResourceResolverfor a system user that hasn't been installed yet, bundle activation fails. - Security Immutability: Managing system users via mutable packages can lead to orphaned permissions, race conditions, or accidental overwrites during rollouts.
To solve this, AEM uses Sling Repository Initialization (repoinit).
The Repoinit Execution Lifecycle
Repoinit scripts are Configuration Admin scripts executed when the RepositoryInitializer configuration is registered. They run early enough that application logic can rely on the declared resources, while content packages are installed afterward. A script that targets paths under /apps or /libs must create its own prerequisites because package content is not present yet.
- Declarative repeatability: Repoinit performs explicit operations atomically and skips statements whose requested state already matches. Write scripts so repeated startup execution remains safe.
- Storage Location: Repoinit scripts are stored as OSGi factory configurations (
org.apache.sling.jcr.repoinit.RepositoryInitializer) inside theui.configmodule:
ui.config/src/main/content/jcr_root/apps/myproject/osgiconfig/config/
└── org.apache.sling.jcr.repoinit.RepositoryInitializer~myproject.config
scripts=["create service user myproject-reader-service with path system/cq:services/myproject\ncreate path (sling:Folder) /content/mybrand\nset ACL for myproject-reader-service\n allow jcr:read on /content/mybrand\nend"]
Repoinit Syntax Breakdown
Repoinit features a specialized, human-readable Domain Specific Language (DSL). The AD0-E128 exam tests syntax patterns across four essential operations:
1. Creating Service Users
Service users (system users) must be created with an explicit intermediate path under system/:
create service user data-importer-service with path system/cq:services/myproject
create service user cache-invalidator with path system/cq:services/myproject
2. Creating Intermediate Folder Hierarchies
Before setting ACLs on a repository path, the path must exist. Repoinit allows creating paths with specific JCR primary types:
# Create JCR folder structures with explicit nodetypes
create path (sling:Folder) /content/dam/myproject
create path (nt:unstructured) /var/myproject/cache
create path (sling:OrderedFolder) /content/experience-fragments/myproject
3. Setting JCR Access Control Lists (ACLs)
ACL blocks declare fine-grained permissions for specific service users or user groups:
set ACL on /content/myproject, /content/dam/myproject
# Allow read and property modifications
allow jcr:read, jcr:modifyProperties on /content/myproject for data-importer-service
# Allow full content authoring under DAM
allow jcr:all on /content/dam/myproject for data-importer-service
# Explicitly deny access to restricted branches
deny jcr:all on /content/myproject/confidential for data-importer-service
end
Common JCR privileges used in repoinit:
jcr:read: View nodes and read properties.jcr:modifyProperties: Add, update, or remove properties on existing nodes.jcr:addChildNodes: Create new child nodes under the path.jcr:removeNode/jcr:removeChildNodes: Delete nodes.jcr:all: Grants all standard JCR privileges.
4. Registering Namespaces and Node Types
Repoinit can register custom JCR namespaces and Compact Node Type Definitions (CND) dynamically:
register namespace (mybrand) http://www.mybrand.com/jcr/1.0
register nodetypes
<<
[mybrand:ProductItem] > nt:unstructured
- mybrand:sku (string) mandatory
- mybrand:price (double)
>>
Service User Mapping Architecture
In modern AEM, obtaining an administrative JCR session via loginAdministrative() is completely deprecated and blocked due to serious security vulnerabilities. Backend services must authenticate using Service Resource Resolvers mapped to specific system users.
Step 1: Configure ServiceUserMapperImpl.amended
To bind a Java bundle to a system user, create an OSGi configuration in ui.config:
org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~myproject.cfg.json:
{
"user.mapping": [
"myproject.core:data-importer=[data-importer-service]"
]
}
myproject.core: TheBundle-SymbolicNameof the Java bundle declared incore/pom.xml.data-importer: The optional, highly recommended subservice name.[data-importer-service]: The service user identifier created in repoinit.
Step 2: Acquire the ResourceResolver in Java
In the Java OSGi service, request the service resource resolver by passing the subservice name into ResourceResolverFactory:
package com.mycompany.myproject.core.services.impl;
import java.util.Collections;
import java.util.Map;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = DataImportService.class)
public class DataImportServiceImpl implements DataImportService {
private static final Logger LOG = LoggerFactory.getLogger(DataImportServiceImpl.class);
private static final String SUBSERVICE_NAME = "data-importer";
@Reference
private ResourceResolverFactory resolverFactory;
@Override
public void importCatalogData() {
Map<String, Object> authInfo = Collections.singletonMap(
ResourceResolverFactory.SUBSERVICE, SUBSERVICE_NAME
);
// Acquire the scoped service resolver inside try-with-resources
try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(authInfo)) {
// Perform repository operations safely scoped to data-importer-service ACLs
LOG.info("Successfully acquired ServiceResourceResolver for user: {}", resolver.getUserID());
} catch (LoginException e) {
LOG.error("Unable to obtain ServiceResourceResolver for subservice: {}", SUBSERVICE_NAME, e);
}
}
}
Exam Trap: Never hardcode credentials or pass
nullauthentication maps intoresolverFactory.getServiceResourceResolver(). If the subservice name in Java does not match theServiceUserMapperImpl.amendedconfiguration string,ResourceResolverFactorythrows aLoginException.
A developer working on AEM as a Cloud Service needs to test a small Java bug fix in an OSGi service against a real cloud environment without waiting 30 minutes for a full Cloud Manager pipeline. Which tool and command achieves this?
Why must system users and initial repository permissions in AEM as a Cloud Service be created via Sling Repoinit scripts rather than included inside a content package?
Review the following Sling Repoinit snippet: create service user catalog-importer with path system/cq:services/retail set ACL on /content/retail/catalog allow jcr:read, jcr:modifyProperties, jcr:addChildNodes on /content/retail/catalog for catalog-importer end What is required in OSGi configuration for a custom Java bundle with symbolic name com.retail.core to obtain a ResourceResolver using the catalog-service subservice?
Which Adobe I/O CLI command restores a Rapid Development Environment (RDE) back to its pristine baseline state, removing all developer-installed bundles, configs, and packages?