This is Part Three of a four-part series on Adobe Experience Manager as a Cloud Service. Part One provided an overview of AEM Cloud Service as compared with AEM 6.5. Part Two covered the unique operations and deployment features of AEM Cloud Service. This part describes how AEM development changes under AEM Cloud Service, along with migration options and lessons learned using AEM Cloud Service to date. Part Four completes the series with an overview of the tools that Adobe provides to facilitate migrating to AEM Cloud Service.
The technical foundation for AEM development has been fairly stable for many years, consisting of Java, the Java Content Repository (JCR) API, Apache Sling, and OSGI services for back-end development, and HTML, CSS, JavaScript, and Sightly/HTL for front-end development. Perhaps unsurprisingly, this does not change in AEM Cloud Service. What does change are the following (each of which is covered in more detail below):
- AEM Cloud Service SDK – There is a specific AEM Cloud Service SDK.
- Maven project archetype – AEM Cloud Service uses the same Maven project archetype as AEM 6.5; however a special flag is used to generate an AEM Cloud Service-compatible project.
- AEM Cloud Service development restrictions – There are many restrictions on AEM Cloud Service development, driven by a combination of the container-based architecture and the need for AEM instances to be guaranteed to be consistent.
AEM Cloud Service SDK
The AEM Cloud Service SDK can be downloaded from the Adobe Software Distribution site and consists of the AEM Cloud Service Quickstart JAR file and zip files containing the Dispatcher tools for Windows and Linux operating systems. The Quickstart JAR can be executed in the same manner as the AEM 6.5 Quickstart JAR to launch a local AEM instance. It differs in the sense that it (and the SDK overall) is associated with a specific AEM Cloud Service release and is updated several times per month, mirroring the AEM Cloud Service release schedule. This means that developers are likely to reinstall AEM several times during the life of a project to stay current with the version in Production. This compares with AEM 6.5, where the version used during the life of a project is much more stable, with perhaps a single new fix pack being applied to the existing instance during the project. It is relatively trivial to move to using a new AEM Cloud Service Quickstart JAR however – all that is needed on top of redeploying the Maven build is transferring content to the new instance via Package Manager.
Maven Project Archetype
To generate a Maven project for AEM Cloud Service, you run the Maven command line to generate the project from the archetype, passing in the command line parameter aemVersion=cloud. This ensures that the project gets generated with the following differences:
- Dispatcher files are in the AEM Cloud Service format.
- Core Components are not included in the build (as they are embedded in AEM Cloud Service by default).
- The AEM Analyzer Maven plugin is included in order to run checks that ensure that potential AEM Cloud Service build issues are identified in the local build.
AEM Cloud Service Development Restrictions
In order to ensure that AEM Cloud Service instances are consistent, certain parts of the repository (/apps and /libs) are defined to be immutable at runtime. I.e. they cannot be modified after AEM starts. One consequence of this is that content packages cannot contain both immutable content and mutable content. Further details on the AEM Cloud Service project structure can be found here.
There are several other restrictions of note, as described in the AEM Cloud Service development guidelines:
- State in memory – Don’t keep state in memory as the AEM instance may get torn down and replaced at any instant.
- State on filesystem – Don’t keep state on the filesystem as the disk storage is specific to the instance and will be disposed of when the AEM instance is torn down (which could be anytime).
- Background tasks – Background tasks and long-running jobs need to be resilient and re-startable because the instance that they start running on may go down.
- Outgoing HTTP connections – These should have short timeouts (< 10 seconds) for the same reason.
- No Classic UI – The Classic UI is not only deprecated, it is completely unavailable – with the exception of the OOTB interface for the External Link Checker.
- JCR updates – Code cannot write to the JCR on the Publish instances
- No reverse replication – Reverse replication agents are not supported except for replicating changes to users’ /home folders.
Development Restrictions specific to AEM Assets
There are also restrictions that are specific to AEM Assets:
- Asset API restrictions – the APIs for creating and updating assets and renditions are not available within AEM Cloud Service.
- DAM Update Asset workflow – this workflow is no longer available as asset processing is now performed via external microservices. It is possible to create custom microservices using the Asset Compute Service and Adobe App Builder (which used to be called Project Firefly) or to add post-processing workflows that execute once the microservices have completed processing.
Example Use Cases Limited by AEM Cloud Service Development Restrictions
The good news is that these restrictions are largely irrelevant to the majority of AEM development tasks e.g. standard component and template development. However, there will be some edge cases where the restrictions will come into play. Examples include:
- Workflow metadata persistence – Customers in some regulated industries require that metadata for approval workflows be persisted for longer than the workflow purge setting. A common way of achieving this is to include a step at the end of the workflow that writes the metadata to the DAM as an asset in JSON or XML format – which is no longer possible as the relevant APIs for creating an asset are unavailable. A workaround is to use the underlying JCR APIs to store the metadata in the node structure. This satisfies the persistence requirement but does make it less convenient for viewing the metadata if/when needed in the future.
- Compliance archiving – Some customers (again in highly-regulated industries) require that compliance information such as approval metadata or screenshots of page content be written to WORM storage so that it can be proven that the information could not have been changed. We have been able to work with the AMS team to create a writeable folder on the AEM Author instance’s file system to which the information can be temporarily written, whereupon an external process pulls the information via FTP and writes it to the WORM storage. This would not be possible in AEM Cloud Service as writing to the filesystem is not allowed; instead the information would need to be pushed to the external service via a web service call or equivalent.
- User-generated content – some websites allow a limited form of user interaction that needs to be persisted e.g. comments or likes on a blog article. Previously such user-generated content could be added directly to the content repository on the Publish instance, reverse replicated to the Author instance and then replicated back out to the rest of the Publish instances. Under AEM Cloud Service this is not possible – instead the user-generated content will need to be written to an external content repository or data store and retrieved dynamically as needed.
AEM Cloud Service Development Best Practices
Part Two of this series mentioned how Adobe will push critical updates to AEM Cloud Service several times per month and feature releases once per month. These updates can contain changes to AEM APIs and can deprecate or remove APIs and/or third-party libraries. In order to mitigate the risk of components breaking as a result of these updates, it is important that developers follow AEM best practices, particularly where it comes to extending OOTB features or core components.
- Use overlays only where necessary and minimize the extent of the code that is copied and modified.
- Use patterns such as Sling Resource Merger and Sling Model Delegation when extending core components.
- Use JUnit and mocking frameworks such as Mockito and wcm.io to create automated unit tests that test the Sling models, servlets and other Java classes that provide the server-side functionality for your website.
- Consider the use of integration testing and front-end testing to further raise the test code coverage and reduce the risk that an AEM Cloud Service update could break your website.
Cloud Service Development Debugging
From a debugging perspective, it is important to note that changing the log level requires a redeployment as it is an update to an OSGI configuration. For this reason, changes to log levels in Production should be used with care as it will take a redeployment (i.e. a minimum of one hour) to change the log level back again, during which time logs could be filled and performance degraded.
Additional Lessons Learned with AEM Cloud Service
Here are a few lessons learned with respect to AEM Cloud Service outside of what has already been discussed:
- Many features of ACS Commons are incompatible with AEM Cloud Service. In addition, as of the time of writing this article, including ACS Commons in your AEM Cloud Service build will result in a number of significant code quality issues being raised. Tread warily.
- Preview servers cannot be targeted with a run mode for OSGI configurations; instead they show as regular Publish instances. This means that if you have code that you only want to run for the actual Production Publish instances (e.g. loading the Production Launch library), you will need to rely on the fact that the server name for Preview instances starts with “preview-“ in order to exclude them.
- The default Launch code for setting Target cookies needs to be slightly different for *.adobeaemcloud.com domains (e.g. for Author and Preview servers) as it needs to target the sub-domain (e.g. preview-pXXXXX-eYYYYYY.adobeaemcloud.com) instead of the overall domain (adobeaemcloud.com). This is because the latter is known to be a public domain used by a significant number of different customers/brands, so setting a cookie at that level would effectively create a global tracking cookie for everyone on that domain. For this reason, browsers will prevent a cookie from being created on that domain. This does not impact Publish servers using custom (and customer-specific) domains.
- Longer deployment times including for Dev environments make code reviews and effective unit testing of features even more essential.
- As of the time of writing there is a bug in the Dispatcher Tools that prevents “flexible” mode from working in your local Dispatcher instance (but it works in the actual Dispatcher instances in the Adobe cloud).
- Adobe has a hard block on the /welcome path for AEM Cloud Service deployments, so it cannot be used as a vanity URL.
- (We’ve mentioned this before) Doing a full redeployment of the entire codebase just to fix a Dispatcher filter or rewrite rule is extremely annoying. For this reason, test Dispatcher changes carefully using the local Dispatcher Tools.
Summary
To summarize, development for AEM Cloud Service involves many familiar technologies and many restrictions that will not impact typical component and template development but should be taken into consideration when developing anything out of the ordinary.
Comments are closed.