The following picture presents the most famous example of Resource Status framework usage. This warning is displayed at the top of the Template Editor console in AEM when you open a template which is in status Enabled:

A warning, displayed at the top of the Template Editor console in AEM, explaining that current template is not a draft

This article will show how the Resource Status framework is used in synchronization of composites – new feature in Composites module, released in version 6.5.1.

Use Case

A few words for those of you who are not familiar with Composites - this module allows content production teams to aggregate and organize components into reusable, higher order entities (or, using Atomic Design terminology, organisms). Creating composites does not require any specific programming knowledge or skills, basically no development is necessary here. Once created, a composite is not just a simple sum of its elements. It can be easily dragged and dropped on multiple pages at a minimal cost, while ensuring the ability to edit each composite instance (and its elements) on each page individually, according to specific needs. These factors alone significantly accelerate the authors' work. What makes composite really powerful, however, is the fact, that it can act as snippet, on demand updating it's occurrences, at the same time keeping the best advantages of being a customizable per-page template.

To explain a bit more - author can decide, that instances of given composite need common updates, for example some components within shall be reordered, added, resized, given new content or styles etc. All the author has to do is:

  • Choose which elements - components or groups of components within composite - should be updated (in other words, synchronized with definition), and which should stay instance-specific. Elements to synchronize are placed in locked Layout Container components. Author can easily lock or unlock layout container using dedicated custom icon on layout container's hoverbar.
  • Edit composite definition according to new design.
  • Fire the synchronization process to apply selected changes to all instances of the composite.

There were a few interesting business and technical aspects to cover while implementing synchronization of composites feature. Among others, we needed to provide a convenient and readable synchronization interface:

  • To inform authors about synchronization scope, impact and potential risk. Impact means displaying full list of links to pages where composite is used; even hundreds of separate items grouped in pages and templates.
  • For authors to decide which aspects of composite shall be updated. By default, it's composite structure and grid settings, additionally components' styles, content and configuration can be updated.
  • To ensure that authors (working on composite page) are always informed that it's currently being synchronized. This should be costless from authors’ point of view.

Built-in AEM workflows, with their steps and notifications, have been considered as a potential solution but ultimately rejected. Synchronization runs asynchronously and shouldn't block author‘s further activities on composite definition page. Furthermore, no additional decision or approval steps are necessary after the process has started. For these reasons, using workflows would be an unnecessary overhead.

For any given composite page, the author can use a custom wizard that we've built to guide him through the synchronization process. The first step presents what pages containing instances of the composite will be synchronized:

Synchronization Wizard Step 1 of 3 - a total number of pages to be synchronized, followed by a list of page titles and paths

In the second step author decides on synchronization aspects:

Synchronization Wizard Step 2 of 3 - where the user can choose to only synchronize the structure and the grid settings, or to include the styles and content associated with the composite as well

The third step is a summary and confirmation step. When author confirms to proceed, synchronization process starts in the background (and Sling Jobs mechanism is used in the backend layer).

But how to notify authors who open composite page, that synchronization process is in progress? It may happen that this process is time-consuming if composite is complex and widely used on many pages. In that case, authors should be warned that this page is being currently synchronized. In addition, it would be nice to display how many instances are already done to the total number of instances. This is where AEM Resource Status framework comes into play.

Implementation

AEM Resource Status Framework is quite an old AEM feature, it was introduced in AEM 6.3.

The concept and usage are simple. There are three most basic editor types in AEM: Page, Experience Fragment and Template. On page reload, editor can display custom status resources provided by Resource Status Provider implementations. The mapping between custom status resources and specific editor types is managed as an OSGi configuration.

To implement a new status resource type, two steps are required:

1. OSGI Configuration

Provide a new com.adobe.granite.resourcestatus.impl.CompositeStatusType OSGi configuration, binding the new status type to chosen editor category („editor” for Pages and Experience Fragments, and „templateEditor” for Templates).
(Composite definition pages are simply Experience Fragments pages, therefore dedicated „composite-sync-status” type was registered for „editor” category):

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="sling:OsgiConfig"
    name="editor"
    types="composite-sync-status"/>

2. Provider implementation

Provide com.adobe.granite.resourcestatus.ResourceStatusProvider implementation for registered status type (in our case - "composite-sync-status"):

@Override
public String getType() {
   return "composite-sync-status";
}

Provider implementation checks if status message should be displayed, conditionally building resource status objects, each representing a status to display. Usually it returns one status resource or none if conditions are not checked.

In our example, information about ongoing synchronization process shall be displayed only if this is composite definition page, and synchronization is still ongoing. This is true if there is composite sync dedicated Sling Job currently processing that page. Additional information on number of finished steps and total steps is obtained via Job Executor implementation. Simplified code may look like this:

@Override
public List<ResourceStatus> getStatuses(Resource resource) {
   List<ResourceStatus> statuses = new LinkedList<>();
   if (isCompositeSynchronized(resource)) {                 // check if conditions to display status are met
      EditorResourceStatus status = createStatus(resource); // create status
      statuses.add(status);                                 // and add to result list
   }
   return statuses;
}

To create a ResourceStatus object use com.day.cq.wcm.commons.status.EditorResourceStatus.Builder. It allows to customize message according to needs, for example display it as info, warning, or error variants, add custom icon, or priority:

private EditorResourceStatus createStatus(Resource resource) {
   Job syncJob = getSynchronizatonJob(resource);  // in this case data is gathered from
                                                  // job object, but it can be simply
                                                  // any data related to resource
   return new EditorResourceStatus.Builder(
      this.getType(),
      "Synchronization status",
      "This composite is currently synchronized. <b>" + syncJob.getFinishedProgressStep()
        + "</b> pages of total <b>" + syncJob.getProgressStepCount() + "</b> done." )
      .setVariant(Variant.WARNING)
      .build();
   }
}

And it’s done. If an author opens a page that is currently being synchronized, he will see a status bar like the following:

A warning, displayed on composite definition page, at the top of the Experience Fragments editor, informing about synchronization status

We can see that synchronization is in progress.

Frontend API

The Resource Status framework has yet another feature, that is not used in synchronization implementation. This feature can be useful when additional actions must be performed due to author’s decision, for example it may by performing call to AEM for additional data. If you want to display additional actions in form of links on the editor status bar, provide an EditorResourceStatus object with actions and write a JS implementation of these actions in the form of a clientlib. Remember to add this clientlib to related category: cq.authoring.editor.sites.page (for Pages and Experience Fragments) or cq.authoring.editor.sites.template (for Templates), to make them available in your chosen editor.

Conclusion

Displaying notifications about composites being synchronized, in a way that's lightweight and convenient from the authors' point of view, was an important area to address when implementing the synchronization of composites process. Resource Status framework met these requirements:

  • On composite definition page load, all authors see the status of this page.
  • Authors do not need to check AEM Inbox or AEM workflow/jobs consoles for status.
  • Authors are not blocked on the synchronization process with further work.
  • Implementation is very simple.

To summarize, by gathering and displaying any available information on current page or related resources, it can make authors’ work easier. If you are interested in this article, read more details in this AEM Tutorial.