Developing for Adobe Experience Manager as a Cloud Service: Your Questions Answered

September 9, 2021 | Poorva Jain
blog image for Developing for Adobe Experience Manager as a Cloud Service: Your Questions Answered

Adobe Experience Manager as a Cloud Service (AEMaaCS) offers the latest and greatest from Adobe for marketers using the platform. While providing the well-known simple, intuitive authoring experience that sets it apart as an enterprise CMS, AEMaaCS also promises automatic scaling, zero downtime, as well as automatic product updates.

Now that the platform is available as a Cloud Service, how does it affect the day-to-day for an AEM developer working on customizing the platform? That's why we're here to find out!

Setup & Development

Developers all have to work locally to get their job done—how does that work with AEMaaCS when Adobe sets up the servers for you?

How Do I Get Started?

AEM as a Cloud Service is released as an SDK for local development. It can be downloaded from Experience Cloud Software Distribution. Yep! It's self-service. No need to figure out who to reach out to in the organization for the pesky license.properties file.

Tip: To access the SDK listings, you will need your Adobe Organization to at least be provisioned for AEM as a Cloud Service or AMS.

The SDK consists of various artifacts—Quickstart Jar and Dispatcher Tools. There is also the Java API Jar and Javadoc Jar which can be downloaded through maven tooling, either command line or with your preferred IDE. While all features available in AEM as a Cloud Service are not included in the QuickStart Jar shipped with SDK, it is all you will need to set up your local runtime. You must run the Jar file from the command line!

After numerous failed attempts to start AEM by double-clicking the Jar file, I agree with Adobe when they say that Quickstart Jar does not support double-clicking the Jar file to start AEM locally.

Does Java Have to Be Different?

Yes. AEMaaCS SDK requires Java 11 for the setup of a local AEM Author/Publish instance.

Tip: *Development can still happen on Java 8. But be careful, as the compilation may be different between Java 8 and Java 11.

*If you need to work with different Java versions (for various project reasons), you can do so by using Java version manager tools like jEnv, SDKMan, etc. Most of these are pretty straightforward to install and make the day-to-day working way simpler.

I See a Dispatcher Tools Zip File on Extracting the AEM SDK Zip?

Publish-Side content delivery in AEMaaCS happens via the CDN provided by Adobe for AEMaaCS. Yes, along with AEM Dispatcher and AEM Publish—a CDN layer, Fastly, is always included by default as well; it can't be removed.

Note: Customers can use their CDN on top of the AEM as a Cloud Service CDN.

One difference with Cloud Service is the requirement that all dispatcher configuration is treated as code and stored in git which is deployed via the standard Cloud Manager CI/CD pipeline. The dispatcher tools facilitate configuring, validating, and simulating the Dispatcher locally.

Tip: We don't need to install Apache Server for the Dispatcher to run like in the previous versions of AEM. However, you will need to set up Docker. For local setup, start the Dispatcher inside of the Docker image with the deployment information.

Since AEMaaCS Automatically Updates, How Do I Keep My Local Up to Date?

Updates to AEMaaCS are managed via the Cloud Manager CI/CD pipelines. Production environment updates are automatically managed by Adobe. Non-production environments do NOT auto-update to the latest AEM Release. When an environment is not running the latest publicly available AEM release, the status on Environments Card on the Home Screen will show UPDATE AVAILABLE.

In most cases, AEM version updates incur zero downtime, including for the author instance, which is a cluster of nodes. Rolling updates are possible due to the composite node store feature in Oak.

While auto-update is not a feature available locally, Adobe recommends that you update the AEM SDK at least monthly on, or shortly after, the last Thursday of each month, which is the release cadence for AEM as a Cloud Service "feature releases."

Tip: You must invest in developing automated tests that integrate with the CM pipeline. These tests will be responsible for smoke testing any update coming from the product before applying them.

Do I Have to Do Something Different With My IDE for Building or Development?

No, everything you like to use still works! Tools for speeding up front-end development like aemfed, aemsync, and browser sync all work. No additional settings! You can still use Log Tracer for enabling logs for specific request probing. Filevault will still work as well, and have you checked out AEM Repo yet?

Is Starting a New Codebase Different?

If you are looking to start from scratch, the AEM project archetype version 23 and later have AEM as a Cloud Service support, but starting from scratch isn't always the most efficient course of action. If Bounteous is doing the work, we'll start from our home-grown and ready-to-go project called Activate. It is configured for both the latest version of AEM and AEM as a Cloud service.

What's Different in the Structure of the Project?

AEMaaCS requires a separation of content and code, which means a single content package cannot deploy to both /apps and runtime-writable areas of the repository.

The application must separate code and content into discrete packages for deployment. The recommended application deployment structure relies heavily on what are considered immutable (/apps) and non-immutable areas (everything other than /apps) of the repository. For a detailed view of the updates to the structure, read Content Package Type Validation Forces Rethink of Standard Project Structure for AEM!

Local vs. Remote

That's all well and good for local development, but what's different when my development cycle is complete and my code is being deployed to the remote environments managed by Adobe?

Do I Have to Do Anything When Adobe Provisions My AEMaaCS License?

As a newly onboarded customer, you will have to go through program setup in Cloud Manager. The two important aspects of code building are the environment where you would build to and code and quality for the branch you want to build to this environment. As a part of initial setup, you get to define the environments and set up your CI/CD pipeline.

Once set up, the Cloud Manager Dashboard clearly lists the environments available and the production and non-production pipelines that have been set.

How Does the Build Work?

Nothing changes from a Local Build perspective, you do a maven build and deploy to your local AEM runtime.

Code builds and deployments to your AEM as a Cloud Service environments are facilitated by Adobe Cloud Manager. Cloud Manager is the CI/CD pipeline used to build, test, and deploy new features to AEM as a Cloud Service.

The Cloud Manager landing page lists the programs associated with your organization. On the dashboard for your organization, you will see the environments and pipelines listed. For building code, you can select the pipeline you want to build and just hit Build. Each pipeline goes through a set of sanity checks and rules to make sure that it follows the code standards. Thereafter, build and unit tests are executed before the build image is created to deploy to the chosen environment. If any failures occur during steps in the build process, the execution will pause, requiring action to resolve them.

Note: You will need to sync your code to the Adobe repository. Cloud Manager Pipelines cannot be configured to build from customer/client repositories. Learn more about avoiding limitations for Cloud Manager Pipelines.

Can I Access the AEM System Console?

When developing locally, yes, you have full access to CRXDE Lite and the AEM Web Console. This is different from the Cloud environments where you might still be able to access CRXDE Lite on the development environment but not on stage or production.

Even /apps and /libs can be written directly to local—this is different from Cloud environments where these folders are strictly immutable.

A set of tools for debugging developer environments are available in the Developer Console for dev, stage, and production environments.

As a shortcut, the following Cloud Manager CLI command can be used to launch the developer console based on an environment parameter described below:

aio cloudmanager:open-developer-console <environmentid> --programId <programid>

Tip: If you haven't made friends with the Cloud Manager API, I suggest you do it now! The Cloud Manager API enables interaction with many of the same underlying capabilities exposed through the web UI in a fully programmatic fashion. Cloud Manager plugin for Adobe I/O CLI is very handy if you love doing things via CLI.

How Do OSGi Configurations Differ?

If you've been working on AEM projects, you know that the configuration settings for OSGi components are defined through configuration files that are part of an AEM code project.

But what you might want to know is unlike its prior versions, AEMaaCS supports only the cfg.json OSGi configuration format.

Like earlier, configuration changes are placed in code packages under runmode specific config folders. Runmode resolution is supported by specific OSGi configurations in the following format:

/apps/<application-name>/config.<author|publish>.<dev|stage|prod>/<PID>.cfg.json

Note: No other custom run modes are supported.

There are three types of OSGi configuration values—inline, environment-specific, and secret values.

Sample configuration:
{
"connection.timeout": 1000,
"api-key": "$[secret:server-api-key;default=<value>]",
"url": "$[env:server-url]"
}

While inline values are pretty straightforward, it is interesting to set up and use environment-specific and secret values.

The Cloud Manager API can be used to deploy the new variables and values to a Cloud environment. The author and publish services will be restarted and reference the new values, typically taking a few minutes.

aio cloudmanager:environment:list-variables <environmentid>
aio cloudmanager:set-environment-variables <environmentid> --secret server-api-key "V0amIzdmp0bms0cDV3Nmt4bThucWJ"
aio cloudmanager:set-environment-variables <environmentid> --authorVariable server-url "https://www.aem-my-sample-site.com"
aio cloudmanager:set-environment-variables <environmentid> --publishVariable server-url "https://www.my-sample-site.com"

Tip: While setting up secret and environment variables for the remote might seem a straightforward task via the cloud manager API, doing the same on local might not be. The values for secret variables are read from files. Therefore, for each placeholder, a text file containing the configuration value must be created. All these secret variable values must be stored in the same directory, say "secrets-directory."

Start your AEM java process with -Dorg.apache.felix.configadmin.plugin.interpolation.secretsdir="$(pwd)/secrets-directory" to associate the framework property to read these variable values appropriately.

Likewise, setting up environment variables locally involves setting these as exported bash variables.

How Do I Achieve Consistent Namespaces, Users/Groups, Node Structures, and Types For Each Developer's AEM Instance?

Keeping all the environments in sync with the required basic configuration is a challenge. Enter Sling repoinit language! With immutable instances becoming the norm it has taken a more important role. Repo Init provides instructions, or scripts, that define JCR structures ranging from common node structures like folder trees to users, service users, groups, and ACL definitions.

The key benefits of Repo Init are:

  • They have implicit permissions to perform all actions defined by their scripts.
  • They are always additive.
  • They are invoked early in the deployment lifecycle ensuring all required JCR structures exist by the time code is executed.
  • All the repository-related configurations are managed through code.

It Seems Like There's Stuff Missing on the Remote Environment. What Do I Have to Do Instead?

Yep, all the nifty consoles for development and debugging are not available on CS. The processes outlined for build and deploy for AEM as a Cloud Service strive to ensure everything through a code-based approach, which endeavors to keep all environments working the same way as each other. AMS Support to help you debug issues in higher environments is available but limited.

Do consider the Development Environment your baseline, not your local instance. Yes, this might sound a bit different than what we are used to as developers. By including a build and deployment to the Development environment in your "Definition of Done" on your tasks, you will not only help keep your Sprints on track but it will help you uncover any bugs caused by differences in the SDK vs a running Cloud Service AEM instance.

The Developer Console is the closest you can get to having access to various consoles for any debugging needs. Each AEM as a Cloud Service environment has its own Developer Console. The group of Author and Publish services in a given environment are referred to as pods. For the selected pod, the Developer console allows you to generate status information for Bundles, Components, Configurations, Oak Indexes, OSGi Services, and Sling Jobs.

You can also see the result of resolution of JavaPackages (similar to Dependency Finder), determine script resolution for servlets, or get an insight into the query performance. Consider it a read-only access to the OSGi Web Console!

Another common requirement for debugging is access to the log files of the various environments. With AEM as a Cloud Service, the log files of the different pods in the Author and Publish services are made available via the Cloud Manager or Adobe I/O CLI. Cloud Manager allows for downloading environment-specific log files, which can then be inspected via any log analysis tools. Adobe I/O with the Cloud Manager plugin provides the ability to tail as well as download logs.

Tip: All log activity for a given environment’s AEM service (Author, Publish/Publish Dispatcher) is consolidated into a single log file, even if different pods within that service generate the log statements. So keep an eye out for pod IDs when you are skimming through the logs. 
 
Additional Resources: