The fundamentals of code development are similar in AEM as a Cloud Service compared to the AEM On Premise and Managed Services solutions. Developers write code and test it locally, which is then pushed to remote AEM as a Cloud Service environments. Cloud Manager, which was an optional content delivery tool for Managed Services, is required. This is now the sole mechanism for deploying code to AEM as a Cloud Service dev, stage, and production environments. For quick feature validation and debugging prior to deploying those aforementioned environments, code can be synced from a local environment to a Rapid Development Environment.
The update of the AEM version is always a separate deployment event from pushing custom code. Viewed in another way, custom code releases should be tested against the AEM version that is on production since that is what it will be deployed on the top. AEM version updates that happen after that, which will be frequent and are automatically applied. They are intended to be backward compatible with the customer code already deployed.
The rest of this document will describe how developers should adapt their practices so they work with both AEM as a Cloud Service’s Version updates and customer updates.
For previous AEM solutions, the most current AEM version changed infrequently (roughly annually with quarterly service packs) and customers would update the production instances to the latest quickstart on their own time, referencing the API Jar. However, AEM as a Cloud Service applications are automatically updated to the latest version of AEM more often, so custom code for internal releases should be built against the latest AEM version.
Like for existing non-cloud AEM versions, a local, offline development based on a specific quickstart will be supported and is expected to be the tool of choice for debugging in the majority of cases.
There are subtle operational differences between how the application behaves on a local machine versus the Adobe Cloud. These architectural differences must be respected during local development and could lead to a different behavior when deploying on the cloud infrastructure. Because of these differences it is important to perform the exhaustive tests on dev and stage environments before rolling out new custom code in production.
In order to develop custom code for an internal release, the relevant version of the AEM as a Cloud Service SDK should be downloaded and installed. For additional information about using the AEM as a Cloud Service Dispatcher Tools, see this page.
The following video provides a high level overview on how to deploy code to AEM as a Cloud Service:
Customers deploy custom code to cloud environments through Cloud Manager. It should be noted that Cloud Manager transforms locally assembled content packages into an artifact conforming to the Sling Feature Model, which is how an AEM as a Cloud Service application is described when running in a cloud environment. As a result, when looking at the packages in Package Manager on Cloud environments, the name will include “cp2fm” and the transformed packages have all metadata removed. They cannot be interacted with, meaning they cannot be downloaded, replicated, or opened. Detailed documentation about the converter can be found here.
Content packages written for AEM as a Cloud Service applications must have a clean separation between immutable and mutable content and Cloud Manager will only install the mutable content, also outputting a message like:
Generated content-package <PACKAGE_ID> located in file <PATH> is of MIXED type
The rest of this section will describe the composition and implications of immutable and mutable packages.
All content and code persisted in the immutable repository must be checked into git and deployed through Cloud Manager. In other words, unlike current AEM solutions, code is never deployed directly to a running AEM instance. This ensures that the code running for a given release in any Cloud environment is identical, which eliminates the risk of unintentional code variation on production. As an example, OSGI configuration should be committed to source control rather than managed at runtime via the AEM web console’s configuration manager.
As application changes due to the Blue-Green deployment pattern are enabled by a switch, they cannot depend on changes in the mutable repository with the exception of service users, their ACLs, nodetypes and index definition changes.
For customers with existing code bases, it is critical to go through the repository restructuring exercise described in AEM documentation to ensure that content formerly under the /etc is moved to the right location.
Some additional restrictions apply for these code packages, for example install hooks are not supported.
As mentioned above, OSGI configuration should be committed to source control rather than through the web console. Techniques to do so include:
Read more about OSGI configuration at Configuring OSGi for AEM as a Cloud Service.
In some cases it might be useful to prepare content changes in source control so it can be deployed by Cloud Manager whenever an environment was updated. For example, it might be reasonable to seed certain root folder structures or line up changes in editable templates to enable policies in those for components that were updated by the application deployment.
There are two strategies to describe the content that will be deployed by Cloud Manager to the mutable repository, mutable content packages and repoinit statements.
Content such as folder path hierarchies, service users, and access controls (ACLs) are typically committed into a maven archetype-based AEM project. Techniques include exporting from AEM or writing directly as XML. During the build and deployment process, Cloud Manager packages the resulting mutable content package. The mutable content is installed at 3 different times during the deploy phase in the pipeline:
Ahead of startup of new version of application:
During startup of new version of application but ahead of switchover:
After switchover to new version of application:
/conf
) (add, modify, remove)It is possible to limit mutable content installation to author or publish by embedding packages in an install.author or install.publish folder under /apps
. Restructuring to reflect this separation was done in AEM 6.5 and details around recommended project restructuring can be found in the AEM 6.5 documentation.
Content packages are deployed to all environment types (dev, stage, prod). It is not possible to limit deployment to a specific environment. This limitation is in place to ensure the option of a test run of automated execution. Content that is specific to an environment requires manual installation via Package Manager.
Also, there is no mechanism to rollback the mutable content package changes after they’ve been applied. If customers detect a problem, they can choose to fix it in their next code release or as a last resort, restore the entire system to a point in time before the deployment.
Any included 3rd party packages must be validated as being AEM as a Cloud Service Service compatible, otherwise its inclusion will result in a deployment failure.
As mentioned above, customers with existing code bases should conform to the repository restructuring exercise necessitated by the 6.5 repository changes described in the AEM 6.5 documentation.
For the following cases, it is preferable to take the approach of hand coding explicit content creation repoinit
statements in OSGI factory configurations:
Create/delete/disable service users
Create/delete groups
Create/delete users
Add ACLs
Definition of ACLs requires the node structures to be already present. Thus, preceding create path statements might be necessary.
Add path (for example for root folder structures)
Add CNDs (nodetype definitions)
Repoinit is preferable for these supported content modification use cases due to the following benefits:
When Cloud Manager deploys the application, it executes these statements, independently from the installation of any content packages.
To create repoinit statements, follow the below procedure:
org.apache.sling.jcr.repoinit.RepositoryInitializer
in a configuration folder of the project. Use a descriptive name for the configuration like org.apache.sling.jcr.repoinit.RepositoryInitializer~initstructure./content
before /content/myfolder
, before /content/myfolder/mysubfolder
. For ACLs being set on low level structures it is recommended to set those on a higher level and work with a rep:glob
restriction. For example (allow jcr:read on /apps restriction(rep:glob,/msm/wcm/rolloutconfigs))
.For ACLs defined for nodes underneath /apps
or /libs
the repoinit execution will start on a blank repository. The packages are installed after repoinit so statements cannot rely on anything defined in the packages but must define the preconditions like the parent structures underneath.
For ACLs the creation of deep structures might be cumbersome, therefore is more reasonable to define an ACL on a higher level and constrain where it is supposed to act via a rep:glob restriction.
More detail about about repoinit can be found in the Sling documentation
There are use cases where a content package should be installed as a “one off”. For example importing specific content from production on to staging in order to debug a production issue. For these scenarios, Package Manager can be used in AEM as a Cloud Service environments.
Since Package Manager is a runtime concept, it is not possible to install content or code into the immutable repository, so these content packages should only consist of mutable content (mainly /content
or /conf
). If the content package includes content that is mixed (both mutable and immutable content), only the mutable content will be installed.
The Package Manager UI might return an undefined error message if a package takes longer than 10 minutes to install.
This is not due to an error with the installation, but to a timeout that Cloud Service has for all requests.
Do not retry the installation if you see such an error. The installation is proceeding correctly in the background. If you do restart the installation some conflicts could be introduced by multiple concurrent import processes.
Any content-packages installed via Cloud Manager (both mutable and immutable) will appear in a frozen state in AEM Package Manager’s user interface. These packages cannot be reinstalled, rebuilt or even downloaded, and will listed with a “cp2fm” suffix, indicating their installation was managed by Cloud Manager.
It is common for customers to include pre-built packages from third party sources such as software vendors like Adobe’s translation partners. The recommendation is to host these packages in a remote repository and reference them in the pom.xml
. This is possible for public repositories and also for private repositories with password protection, as described in password protected maven repositories.
If storing the package in a remote repository is not possible, customers can place in a local, file system based Maven repository, which is committed to SCM as part of the project, and referenced by whatever depends on it. The repository would be declared in the project pom as illustrated below:
<repository>
<id>project.local</id>
<name>project</name>
<url>file:${maven.multiModuleProjectDirectory}/repository</url>
</repository>
Any included third party packages must be adhere to the AEM as a Cloud Service Service coding and packaging guidelines described in this article, otherwise its inclusion will result in a deployment failure.
The following Maven POM.xml
snippet shows how 3rd party packages can be embedded in the project’s “Container” package, typically named ‘all’, via the filevault-package-maven-plugin Maven plugin configuration.
...
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
...
<embeddeds>
...
<!-- Include any other extra packages -->
<embedded>
<groupId>com.vendor.x</groupId>
<artifactId>vendor.plug-in.all</artifactId>
<type>zip</type>
<target>/apps/vendor-packages/container/install</target>
</embedded>
<embeddeds>
</configuration>
</plugin>
...
Like AEM updates, customer releases are deployed using a rolling deployment strategy in order to eliminate author cluster downtime under the right circumstances. The general sequence of events is as described below, where Blue is the old version of customer code and Green is the new version. Both Blue and Green are running the same version of AEM code.
New or modified indexes will cause an additional indexing or re-indexing step before the new (Green) version can take on traffic. Details about index management in AEM as a Cloud Service can be found in this article. You can check the status of the indexing job on the Cloud Manager build page and will receive a notification when the new version is ready to take traffic.
The time needed for a rolling deployment will vary depending on the size of the index, since the Green version cannot accept traffic until the new index has been generated.
At this time, AEM as a Cloud Service does not work with index management tools such as ACS Commons Ensure Oak Index tool.
The publication mechanism is backwards compatible with the AEM Replication Java APIs.
In order to develop and test with replication with the cloud ready AEM quickstart, the classic replication capabilities needs to be used with an Author/Publish setup. In the case of the UI entry point on AEM Author has been removed for the cloud, users would go to http://localhost:4502/etc/replication
for configuration.
As detailed above, AEM as a Cloud Service’s rolling deployment strategy implies that both the old and new versions may be operating at the same time. Therefore, be cautious of code changes that are not backwards compatible with the old AEM version that is still operation.
In addition, the old release should be tested for compatibility with any new mutable content structures applied by the new release in the event of roll back, since mutable content is not removed.
Changing service users or ACLs needed to access content or code could lead to errors in the older AEM versions resulting in access to that content or code with outdated service users. To address this behavior, a recommendation is to make changes spread across at least 2 releases, with the first release acting as a bridge before cleaning up in the subsequent release.
If changes to indexes are made, it is important that the Blue version continues to use its indexes until it is terminated, while the Green version uses its own modified set of indexes. The developer should follow the index management techniques described in this article.
If a failure is reported or detected after the deployment, it is possible that a rollback to the Blue version will be required. It would be wise to ensure that the Blue code is compatible with any new structures created by the Green version since the new structures (any mutable content content) will not be rolled back. If the old code is not compatible, fixes will need to be applied in subsequent customer releases.
Rapid Development Environments (or RDEs for short) allow developers to quickly deploy and review changes, minimizing the amount of time needed to test features that are already proven to work on a local development environment.
Unlike regular dev environments, which deploy code via Cloud Manager pipeline, developers use command line tools to sync code from a local development environment to the RDE. Once the changes have been successfully tested in an RDE, they should be deployed to a regular Cloud Development environment through the Cloud Manager pipeline, which will put the code through the appropriate quality gates.
In existing AEM solutions, customers have the option of running instances with arbitrary run modes and apply OSGI configuration or install OSGI bundles to those specific instances. Run modes that are defined typically include the service (author and publish) and the environment (rde, dev, stage, prod).
AEM as a Cloud Service on the other hand is more opinionated about which run modes are available and how OSGI bundles and OSGI configuration can be mapped to them:
<service>.<environment_type>
is being supported whereas these have to be used in this particular order (for example author.dev
or publish.prod
). The OSGI tokens should be referenced directly from code rather than using the getRunModes
method, which will no longer include the environment_type
at runtime. For more information, see Configuring OSGi for AEM as a Cloud Service.install.author
or install.publish
.AEM as a Cloud Service does not allow using run modes to install content for specific environments or services. If a development environment needs to be seeded with data or HTML that is not in the staging or production environments, package manager can be used.
The supported runmode configurations are:
The OSGI configuration that has the most matching runmodes is used.
When developing locally, a runmode startup parameter, -r
, is used to specify the runmode OSGI configuration.
$ java -jar aem-sdk-quickstart-xxxx.x.xxx.xxxx-xxxx.jar -r publish,dev
Maintenance Task configurations must be persisted in source control since the Tools > Operations screen will no longer be available in Cloud environments. This has the benefit of ensuring that changes are intentionally persisted rather than reactively applied and perhaps forgotten. Please reference the Maintenance Task article for additional information.