---
title: Asset Workflow customisation in AEM as a Cloud Service
description: Out of the box, AEM workflows do a ton, but when it comes to letting the author add a variable at execution, customization is needed. We outline that here.
image: https://blog.3sharecorp.com/hubfs/Blog%20Content/2024%20Blog%20images/droplets.png
---

[![3SHARE_LOGO_WHITE_2018](https://blog.3sharecorp.com/hs-fs/hubfs/2017%20Website%20Assets/Logos/High%20Res/3SHARE_LOGO_WHITE_2018.png?width=266&height=54&name=3SHARE_LOGO_WHITE_2018.png "3SHARE_LOGO_WHITE_2018")](https://www.3sharecorp.com)

![](https://blog.3sharecorp.com/hubfs/Blog%20Content/2024%20Blog%20images/droplets.png)

# Asset Workflow customisation in AEM as a Cloud Service

Jorge Chércoles, July 2, 2024

The functionality of Assets workflows is expansive from the simple approval workflow to the complex one, encapsulating  multiple data points and destinations. When it comes to using Adobe Experience Manager (AEM) workflows, developers and authors will find a lot of what they need already built in but for some use cases, like the one outlined below, customization is necessary.

## Out of the Box vs Custom Workflow Solutions

AEM provides two out-of-the-box ways of adding extra information in a workflow process:

- **Dialog Participant Step**: Requires the interaction of the user from the inbox and prevents the workflow from continuing until the user approves/rejects the task.
- **Workflow process arguments**: Requires a custom parser (e.g: [https://joao.ws/parsing-aem-workflow-arguments/](https://joao.ws/parsing-aem-workflow-arguments/)) to extract the information and needs to be hardcoded in the workflow. If this information needs to vary between executions, it has to be modified from the “Workflow admin console”.

Both have their use cases, and can be used when needed. However, there is another use case that is not covered by AEM: Dynamic configuration per workflow execution directly before launching.

In other words, letting the author (or executor) of the workflow make a decision at the time that they are launching the workflow. Solving for this use case required integrating custom forms within the launch step when executing workflows for one or more assets. How we did this is outlined below.

### Implementation

#### Step 1 - Custom Workflow Process

Like any other custom workflow process implementation, we need to create a Java class that implements the interface com.adobe.granite.workflow.exec.WorkflowProcess.

We will then access the workflow metadata using the *WorkItem.getWorkflow().getMetadataMap()* method, where the key is the input name of the dialog field.

```
@Component(service = WorkflowProcess.class, property = {"process.label=Dummy Workflow Process"})
public class DummyWorkflow implements WorkflowProcess {

    private static final Logger LOGGER = LoggerFactory.getLogger(DummyWorkflow.class);

    public void execute(WorkItem workItem, WorkflowSession wfSession, MetaDataMap metaDataMap) {
        MetaDataMap map = workItem.getWorkflow().getMetaDataMap();
        LOGGER.info("DummyWorkflow - init");
        map.forEach((key, value) -> LOGGER.info("DummyWorkflow - MetaDataMap: {} -> {}", key, value));
    }
}
```

This will allow us to select our custom Workflow Process inside a "Process Step" in our workflow model.  
For the workflow model example refer to [https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.content/src/main/content/jcr_root/var/workflow/models/dummy-workflow-model.xml](https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.content/src/main/content/jcr_root/var/workflow/models/dummy-workflow-model.xml).

#### Step 2 - Custom dialog | Workflow admin console

### ![Custom dialog - Workflow admin console](https://blog.3sharecorp.com/hs-fs/hubfs/Custom%20dialog%20-%20Workflow%20admin%20console.png?width=2766&height=1458&name=Custom%20dialog%20-%20Workflow%20admin%20console.png)

When running a workflow from the *“Workflow admin console”*, the resource that handles the rendering can be found under */libs/cq/workflow/admin/console/content/models/runmodeldialog*.

If we inspect the node in the JCR repository, we can find a descendant node *items/form/items/extraItems/items/include* with a reference to a resource under *cq/workflow/extensions/models/runmodeldialog*.

Find below an example of an extension with a custom form:

```
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0"
          jcr:primaryType="nt:unstructured"
          jcr:title="Dummy Workflow"
          sling:resourceType="granite/ui/components/coral/foundation/form/container">
    <items jcr:primaryType="nt:unstructured">
        <dummy-container
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/container">
            <granite:data
                    jcr:primaryType="nt:unstructured"
                    workflow-node="${requestPathInfo.resourcePath}"
                    workflow="/var/workflow/models/dummy-workflow-model"/>
            <granite:rendercondition
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/renderconditions/or">
                <workflow-models
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/renderconditions/simple"
                        expression="${requestPathInfo.suffix == '/var/workflow/models/dummy-workflow-model'}"/>
                <assets
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/renderconditions/simple"
                        expression="${requestPathInfo.suffix == null}"/>
            </granite:rendercondition>
            <items jcr:primaryType="nt:unstructured">
                <dummy-select
                        jcr:primaryType="nt:unstructured"                        granite:rel="cq-common-admin-timeline-toolbar-actions-workflow-select"
                        sling:resourceType="granite/ui/components/coral/foundation/form/select"
                        required="{Boolean}true"
                        emptyText="Dummy Select"
                        fieldLabel="Dummy Select"
                        name="dummy-select">
                    <items jcr:primaryType="nt:unstructured">
                        <item1 jcr:primaryType="nt:unstructured" text="Item 1" value="item-1"/>
                        <item2 jcr:primaryType="nt:unstructured" text="Item 2" value="item-2"/>
                        <item3 jcr:primaryType="nt:unstructured" text="Item 3" value="item-3"/>
                        <item4 jcr:primaryType="nt:unstructured" text="Item 4" value="item-4"/>
                    </items>
                </dummy-select>
                <dummy-text
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                        fieldLabel="Dummy Text"
                        name="dummy-text"/>
            </items>
        </dummy-container>
    </items>
</jcr:root>
```

For a complete example, refer to: [https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/cq/workflow/extensions/models/runmodeldialog/](https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/cq/workflow/extensions/models/runmodeldialog/)

If we want more fields, we can add them here, following the same structure as the `<dummy-container/>`. The most important nodes are the `granite:data` and `granite:rendercondition`.

`granite:data` exposes two attributes. These two attributes will be used later on when we create the clientlib.

- `data-workflow-node` exposes the node path. It will be used to request the form directly via HTTP GET.
- `data-workflow` exposes the workflow path associated to this form.

`granite:rendercondition` defines when this form will be rendered. These two render conditions are required to make it work. In case you need custom render conditions, refer to: [https://joao.ws/aem-granite-render-conditions/](https://joao.ws/aem-granite-render-conditions/)

- `workflow-models` is true when the suffix of the current request is equal to our workflow. When the dialog is requested from the “Workflow admin console”, the request suffix stores the requested workflow model. `assets` is true when there is no suffix in the request. When the dialog is requested from the “Timeline side panel”, we need to render the form. Visibility will be handled in the clientlib.

Once the node is deployed, the form should start appearing in the “Workflow admin console”, as shown in the image at the beginning of this section.

ℹ️ Custom forms can be built the same way we do with the component dialogs, however the show/hide feature would not work. Although, If that feature is needed you can check out our previous post about it: [https://blog.3sharecorp.com/show-and-hide-dialog-fields-based-on-any-field-type](https://blog.3sharecorp.com/show-and-hide-dialog-fields-based-on-any-field-type) 😉

#### Step 3 - Custom dialog | Timeline side panel

![Custom dialog - Timeline side panel (Asset Details view)-1](https://blog.3sharecorp.com/hs-fs/hubfs/Custom%20dialog%20-%20Timeline%20side%20panel%20(Asset%20Details%20view)-1.png?width=904&height=476&name=Custom%20dialog%20-%20Timeline%20side%20panel%20(Asset%20Details%20view)-1.png)

![Custom dialog - Timeline side panel-1](https://blog.3sharecorp.com/hs-fs/hubfs/Custom%20dialog%20-%20Timeline%20side%20panel-1.png?width=904&height=476&name=Custom%20dialog%20-%20Timeline%20side%20panel-1.png)

ℹ️ Note: Bulk action can also be done when selecting more than one asset in the assets page.

Unlike with the “Workflow admin console”, the “Asset timeline side panel” does not support the include of custom forms in the dialog. Therefore, we have to overlay the dialog under */libs/dam/gui/coral/content/commons/sidepanels/timeline/items/toolbar/items/workflows/items/form*

For a code example, refere to [https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dam/gui/coral/content/commons/sidepanels](https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dam/gui/coral/content/commons/sidepanels)

#### Step 4 - Custom dialog | Create workflow button

![Custom dialog - Create workflow button](https://blog.3sharecorp.com/hs-fs/hubfs/Custom%20dialog%20-%20Create%20workflow%20button.png?width=2880&height=1518&name=Custom%20dialog%20-%20Create%20workflow%20button.png)

As with the “Asset timeline side panel,” we have to enable the inclusion of custom forms in the dialog. For this, we have to overlay the dialog under */libs/dam/gui/content/commons/createworkflowdialog*.

For a code example, refer to [https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dam/gui/content/commons/createworkflowdialog/](https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dam/gui/content/commons/createworkflowdialog/)

#### Step 5 - Custom clientlib

The custom form in the “Assets timeline side panel” and the “Create workflow dialog” need to appear only for our workflow. In order to do this we need to create a custom clientlib with the same category and dependencies  as */libs/dam/gui/coral/components/admin/timeline/events/workflow/clientlibs/workflow*

```
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
          jcr:primaryType="cq:ClientLibraryFolder"
          allowProxy="{Boolean}true"
          categories="[dam.gui.coral.common.admin.timeline.events.workflow]"
          dependencies="[granite.ui.coral.foundation]"/> 
```

For the complete clientlib definition please refer to: [https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dummy/clientlibs/clientlib-workflow/.](https://bitbucket.org/3SHARE/aem-workflow-customisation/src/main/ui.apps/src/main/content/jcr_root/apps/dummy/clientlibs/clientlib-workflow/)

3|SHARE loves being part of the. Adobe developer community and we are happy to share solutions like the above with others. If you liked this one, reach out and let us know. And if you're looking for an outstanding team of architects and developers to help on your AEM project, [get in touch](https://www.3sharecorp.com/contact)!

---

 

Topics: [Adobe Experience Manager](https://blog.3sharecorp.com/topic/adobe-experience-manager), [Development](https://blog.3sharecorp.com/topic/development), [AEM](https://blog.3sharecorp.com/topic/aem), [Tech](https://blog.3sharecorp.com/topic/tech)

- [Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https://blog.3sharecorp.com/workflow-customisation-for-assets-in-adobe-experience-manager-as-a-cloud-service&display=popup&ref=plugin)
- [Share on Twitter](https://www.twitter.com/home?status=Asset%20Workflow%20customisation%20in%20AEM%20as%20a%20Cloud%20Service%20-%20https://blog.3sharecorp.com/workflow-customisation-for-assets-in-adobe-experience-manager-as-a-cloud-service)
- [Share on LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https://blog.3sharecorp.com/workflow-customisation-for-assets-in-adobe-experience-manager-as-a-cloud-service&title=Asset%20Workflow%20customisation%20in%20AEM%20as%20a%20Cloud%20Service&summary=&source=)

### [Jorge Chércoles](https://blog.3sharecorp.com/author/jorge-chercoles)

Jorge Chércoles is an AEM Backend Developer at 3|SHARE. His passion is coding whether that is at work or outside of work. He loves that it gives him the ability to create things out of nothing. At 3|SHARE, Jorge enjoys the work environment and independence he has while doing his job. He is an Adobe Certified Expert having earned the Adobe Experience Manager Sites Developer certification.

[LinkedIn](https://www.linkedin.com/in/jorgechercoles/)

### Popular Posts

### Posts by Topic

- [Adobe Experience Manager (48)](https://blog.3sharecorp.com/topic/adobe-experience-manager)
- [AEM (33)](https://blog.3sharecorp.com/topic/aem)
- [Adobe (20)](https://blog.3sharecorp.com/topic/adobe)
- [Development (19)](https://blog.3sharecorp.com/topic/development)
- [Digital Marketing (19)](https://blog.3sharecorp.com/topic/digital-marketing)
- [Tech (15)](https://blog.3sharecorp.com/topic/tech)
- [Web Content Management System (13)](https://blog.3sharecorp.com/topic/web-content-management-system)
- [3|SHARE Insider (12)](https://blog.3sharecorp.com/topic/3share-insider)
- [Developer Think Tank (12)](https://blog.3sharecorp.com/topic/developer-think-tank)
- [Digital Asset Management (DAM) (10)](https://blog.3sharecorp.com/topic/digital-asset-management-dam)
- [Professional IT Consulting Services (10)](https://blog.3sharecorp.com/topic/professional-it-consulting-services)
- [Adobe Solutions Partner (8)](https://blog.3sharecorp.com/topic/adobe-solutions-partner)
- [Creative Process (7)](https://blog.3sharecorp.com/topic/creative-process)
- [CMS (6)](https://blog.3sharecorp.com/topic/cms)
- [Content Management System (6)](https://blog.3sharecorp.com/topic/content-management-system)
- [Upgrade (6)](https://blog.3sharecorp.com/topic/upgrade)
- [Content Supply Chain (5)](https://blog.3sharecorp.com/topic/content-supply-chain)
- [Culture (5)](https://blog.3sharecorp.com/topic/culture)
- [Customer Experience (5)](https://blog.3sharecorp.com/topic/customer-experience)
- [Remote Operations Management (ROM) (5)](https://blog.3sharecorp.com/topic/remote-operations-management-rom)
- [Testing (5)](https://blog.3sharecorp.com/topic/testing)
- [Webinars (5)](https://blog.3sharecorp.com/topic/webinars)
- [AI (4)](https://blog.3sharecorp.com/topic/ai)
- [Adobe Summit (4)](https://blog.3sharecorp.com/topic/adobe-summit)
- [Personalization (4)](https://blog.3sharecorp.com/topic/personalization)
- [Sanity (4)](https://blog.3sharecorp.com/topic/sanity)
- [Structured Data (4)](https://blog.3sharecorp.com/topic/structured-data)
- [Design (3)](https://blog.3sharecorp.com/topic/design)
- [Headless (3)](https://blog.3sharecorp.com/topic/headless)
- [Leadership (3)](https://blog.3sharecorp.com/topic/leadership)
- [Quality Assurance (3)](https://blog.3sharecorp.com/topic/quality-assurance)
- [AEM Smart Tags (2)](https://blog.3sharecorp.com/topic/aem-smart-tags)
- [Award (2)](https://blog.3sharecorp.com/topic/award)
- [Content Fragments (2)](https://blog.3sharecorp.com/topic/content-fragments)
- [Evolve (2)](https://blog.3sharecorp.com/topic/evolve)
- [Evolve19 (2)](https://blog.3sharecorp.com/topic/evolve19)
- [Integrations (2)](https://blog.3sharecorp.com/topic/integrations)
- [Migration (2)](https://blog.3sharecorp.com/topic/migration)
- [QA (2)](https://blog.3sharecorp.com/topic/qa)
- [UX (2)](https://blog.3sharecorp.com/topic/ux)
- [AEM as a Cloud Service (1)](https://blog.3sharecorp.com/topic/aem-as-a-cloud-service)
- [AWS (1)](https://blog.3sharecorp.com/topic/aws)
- [Accessibility (1)](https://blog.3sharecorp.com/topic/accessibility)
- [Adobe Center of Excellence (1)](https://blog.3sharecorp.com/topic/adobe-center-of-excellence)
- [Apache (1)](https://blog.3sharecorp.com/topic/apache)
- [CDN (1)](https://blog.3sharecorp.com/topic/cdn)
- [ContextHub (1)](https://blog.3sharecorp.com/topic/contexthub)
- [CraftCMS (1)](https://blog.3sharecorp.com/topic/craftcms)
- [Digital Commerce (1)](https://blog.3sharecorp.com/topic/digital-commerce)
- [Digital Experience Solution Partner of the Year (1)](https://blog.3sharecorp.com/topic/digital-experience-solution-partner-of-the-year)
- [Extracirricular (1)](https://blog.3sharecorp.com/topic/extracirricular)
- [Invasion Test (1)](https://blog.3sharecorp.com/topic/invasion-test)
- [LLM (1)](https://blog.3sharecorp.com/topic/llm)
- [Microdata (1)](https://blog.3sharecorp.com/topic/microdata)
- [Rich Snippets (1)](https://blog.3sharecorp.com/topic/rich-snippets)
- [SEO (1)](https://blog.3sharecorp.com/topic/seo)
- [Security (1)](https://blog.3sharecorp.com/topic/security)
- [Vanity URL (1)](https://blog.3sharecorp.com/topic/vanity-url)
- [Web Server (1)](https://blog.3sharecorp.com/topic/web-server)
- [Workfront (1)](https://blog.3sharecorp.com/topic/workfront)

[see all](https://blog.3sharecorp.com/workflow-customisation-for-assets-in-adobe-experience-manager-as-a-cloud-service#)

[![3SHARE_LOGO_WHITE_2018](https://blog.3sharecorp.com/hs-fs/hubfs/2017%20Website%20Assets/Logos/High%20Res/3SHARE_LOGO_WHITE_2018.png?width=266&height=54&name=3SHARE_LOGO_WHITE_2018.png "3SHARE_LOGO_WHITE_2018")](http://3sharecorp.com)

** [info@3sharecorp.com](mailto:info@3sharecorp.com)

** [US: +1 (888) 505-1625](tel:+18885051625)[tel:08003689636](tel:08003689636)

 

[**](https://www.linkedin.com/company/3-share-corporation) [**](https://www.youtube.com/@3share)

Copyright © 2026 [3|SHARE](https://www.3sharecorp.com/). All Rights Reserved.

[Cookie Settings](https://blog.3sharecorp.com/workflow-customisation-for-assets-in-adobe-experience-manager-as-a-cloud-service#) ![](https://px.ads.linkedin.com/collect/?pid=8732449&fmt=gif)