Expand my Community achievements bar.

The first preview of our new Community upgrade is live - check it out now.
SOLVED

Automating DAM asset movement in AEM based on metadata (workflow + configuration issues)

Avatar

Level 2

Hello community, I hope you are all doing well.

 

I'm here to present a challenge I'm currently facing, and I would greatly appreciate any guidance on how to address it.

 

 

**Situation**
I need to automate asset movement in the DAM based on metadata information. Currently, assets have a metadata field containing the destination folder name, but they are located in an incorrect or temporary location.

**Task**
Design an automated workflow in AEM that:
1. Reads the metadata field containing the destination folder name.
2. Locates the corresponding folder in the DAM structure.
3. Automatically moves the asset to that location.

 

The necessary solution includes the workflow configuration, the required steps (reading metadata, searching for the folder, validation, and movement), and any specific code or configuration required.

 

 

I have been working on the solution with code in the repository, relying heavily on AI, however, I haven't obtained the expected results. I created a core file containing all the logic, and in ui.config I added a file that was supposed to link the code I wrote with everything else. I pushed the changes to the repository and deployed it; however, I'm encountering interface problems, such as AEM Sites not displaying all folders. I would appreciate any guidance on how to resolve this, whether I'm missing specific information or files, or if there's any official documentation where I can find information related to this situation.

 

 

Thank you very much for any help you can provide.

1 Accepted Solution

Avatar

Correct answer by
Level 4

Hi @Mailyn_TMo 

Looking at your code and the console errors, I can see the main issues causing the AEM Sites folder display problems. Here's the step-by-step fix:

Step 1: Fix Service User Mapping

Update your 

ui.config
 file 
org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~workflow.cfg.json
:

 

{
  "user.mapping": [
    "aem-guides-wknd.core:workflow-service=workflow-service-user"
  ]
}
 

Issue: Your mapping uses 

aem-oauthtest-project.core
 but your bundle is 
aem-guides-wknd.core
.

 

Step 2: Create Service User

Create 

ui.config/src/main/content/jcr_root/apps/wknd/osgiconfig/config/org.apache.sling.jcr.repoinit.RepositoryInitializer~workflow.cfg.json
:

 

{
  "scripts": [
    "create service user workflow-service-user",
    "set ACL for workflow-service-user",
    "allow jcr:read,jcr:write,jcr:nodeTypeManagement,rep:write on /content/dam",
    "end"
  ]
}
 

Step 3: Fix Your Workflow Process

Update your core class:

@Component(
    service = WorkflowProcess.class,
    property = {
        "process.label=Move Asset by Ravel Metadata"
    }
)
public class MoveAssetByRavelMetadata implements WorkflowProcess {

    @Reference
    private ResourceResolverFactory resolverFactory;

    @Override
    public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) {
        
        Map<String, Object> serviceParams = Map.of(
            ResourceResolverFactory.SUBSERVICE, "workflow-service"
        );
        
        try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(serviceParams)) {
            
            String payloadPath = item.getWorkflowData().getPayload().toString();
            Resource assetRes = resolver.getResource(payloadPath);
            if (assetRes == null) return;

            Asset asset = assetRes.adaptTo(Asset.class);
            if (asset == null) return;

            String folio = asset.getMetadataValue("ravel_Folio");
            String subFolio = asset.getMetadataValue("ravel_SubFolio");
            
            if (folio == null || folio.isEmpty()) return;

            String basePath = "/content/dam/promoxxo/2025/Cerveza/Diseños del Periodo/P8/carpeta";
            String targetPath = subFolio != null && !subFolio.isEmpty() ? 
                basePath + "/subcarpeta" : basePath;
            
            if (resolver.getResource(targetPath) != null) {
                AssetManager assetManager = resolver.adaptTo(AssetManager.class);
                String finalPath = targetPath + "/" + asset.getName();
                assetManager.moveAsset(asset.getPath(), finalPath);
                resolver.commit();
            }
            
        } catch (Exception e) {
            // Add proper logging
        }
    }
}
 
 

Step 4: Update ui.config Filter

Update 

ui.config/src/main/content/META-INF/vault/filter.xml
:

 

<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
    <filter root="/apps/wknd/osgiconfig"/>
</workspaceFilter>
 

Step 5: Deploy and Verify

  1. Build: 

    mvn clean install -PautoInstallPackage

     

  2. Check service user exists: Go to 

    /useradmin
     in AEM

     

  3. Verify permissions: Check that 

    workflow-service-user
     has access to 
    /content/dam

     

Root Cause of Your Issues

The console errors and missing folders are caused by:

  1. Wrong bundle name in service user mapping

  2. Missing service user with proper permissions

  3. Missing repository initialization script

This fix will resolve both the workflow execution and the AEM Sites display issues you're experiencing.

 
 
 

View solution in original post

5 Replies

Avatar

Level 3

Hi @Mailyn_TMo,

 

it's a little bit difficult to understand where and how the UI is displaying "folders". Maybe you can post same screenshots what you talking about. Also it would be helpful, if you could share what you have implemented. Currently, we have no real understand what you exactly did.

 

Patrick

Avatar

Level 2

This is in ui.config file org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~workflow.cfg.json

{
"user.mapping": [
"aem-oauthtest-project.core:workflow-service=workflow-service-user"
]
}

 

 

 

This is in core 

@component(
service = WorkflowProcess.class,
property = {
"process.label=Move Asset by Ravel Metadata"
}
)
public class MoveAssetByRavelMetadata implements WorkflowProcess {

@reference
private ResourceResolverFactory resolverFactory;

@Override
public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) {

try (ResourceResolver resolver =
resolverFactory.getServiceResourceResolver(
Map.of(ResourceResolverFactory.SUBSERVICE, "workflow-service"))) {

String payloadPath = item.getWorkflowData().getPayload().toString();

Resource assetRes = resolver.getResource(payloadPath);
if (assetRes == null) return;

Resource metadataRes = assetRes.getChild("jcr:content/metadata");
if (metadataRes == null) return;

ValueMap metadata = metadataRes.getValueMap();

String folio = metadata.get("ravel_Folio", "");
String subFolio = metadata.get("ravel_SubFolio", "");

if (folio.isEmpty()) return;

Asset asset = assetRes.adaptTo(Asset.class);
if (asset == null) return;

AssetManager assetManager = resolver.adaptTo(AssetManager.class);

String basePath = "/content/dam/promoxxo/2025/Cerveza/Diseños del Periodo/P8/carpeta";
String targetPath = basePath;

if (!subFolio.isEmpty()) {
targetPath += "/subcarpeta";
}

String finalPath = targetPath + "/" + asset.getName();

if (resolver.getResource(targetPath) != null) {
assetManager.moveAsset(asset.getPath(), finalPath);
}

} catch (Exception e) {
// log error
}
}
}

 

 

The attached image with the errors is what I was seeing in the console in AEM Sites instead of the folders appearing as shown in the other image.

 

 

Avatar

Community Advisor

Hi @Mailyn_TMo,
Your approach seems fine. Did you try to debug the code? Most probably the bug is in code. 
Check the following things:
1. Payload path is coming correct 
2. target path is working properly
3. Code is executing properly till last and handle all the edge cases like if the target folder is not there.

Also, make sure to use:
1. resolver.commit() after moveAsset().
2. use asset api to get metadata: 

Resource metadataRes = asset.adaptTo(Resource.class).getChild("jcr:content/metadata");
if (metadataRes == null) return;
ValueMap metadata = metadataRes.getValueMap();

 

Avatar

Level 5

Few questions before we arrive at the solution -

1. Have you implemented any event listener or workflow launcher to call this workflow on updating the asset metadata?

2. What are the list of files did you commit/deploy to AEM?

3. What is the user which you used to login? Is it admin?

4. Did the folder missing issue happen after deploying your latest code?

Avatar

Correct answer by
Level 4

Hi @Mailyn_TMo 

Looking at your code and the console errors, I can see the main issues causing the AEM Sites folder display problems. Here's the step-by-step fix:

Step 1: Fix Service User Mapping

Update your 

ui.config
 file 
org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~workflow.cfg.json
:

 

{
  "user.mapping": [
    "aem-guides-wknd.core:workflow-service=workflow-service-user"
  ]
}
 

Issue: Your mapping uses 

aem-oauthtest-project.core
 but your bundle is 
aem-guides-wknd.core
.

 

Step 2: Create Service User

Create 

ui.config/src/main/content/jcr_root/apps/wknd/osgiconfig/config/org.apache.sling.jcr.repoinit.RepositoryInitializer~workflow.cfg.json
:

 

{
  "scripts": [
    "create service user workflow-service-user",
    "set ACL for workflow-service-user",
    "allow jcr:read,jcr:write,jcr:nodeTypeManagement,rep:write on /content/dam",
    "end"
  ]
}
 

Step 3: Fix Your Workflow Process

Update your core class:

@Component(
    service = WorkflowProcess.class,
    property = {
        "process.label=Move Asset by Ravel Metadata"
    }
)
public class MoveAssetByRavelMetadata implements WorkflowProcess {

    @Reference
    private ResourceResolverFactory resolverFactory;

    @Override
    public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) {
        
        Map<String, Object> serviceParams = Map.of(
            ResourceResolverFactory.SUBSERVICE, "workflow-service"
        );
        
        try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(serviceParams)) {
            
            String payloadPath = item.getWorkflowData().getPayload().toString();
            Resource assetRes = resolver.getResource(payloadPath);
            if (assetRes == null) return;

            Asset asset = assetRes.adaptTo(Asset.class);
            if (asset == null) return;

            String folio = asset.getMetadataValue("ravel_Folio");
            String subFolio = asset.getMetadataValue("ravel_SubFolio");
            
            if (folio == null || folio.isEmpty()) return;

            String basePath = "/content/dam/promoxxo/2025/Cerveza/Diseños del Periodo/P8/carpeta";
            String targetPath = subFolio != null && !subFolio.isEmpty() ? 
                basePath + "/subcarpeta" : basePath;
            
            if (resolver.getResource(targetPath) != null) {
                AssetManager assetManager = resolver.adaptTo(AssetManager.class);
                String finalPath = targetPath + "/" + asset.getName();
                assetManager.moveAsset(asset.getPath(), finalPath);
                resolver.commit();
            }
            
        } catch (Exception e) {
            // Add proper logging
        }
    }
}
 
 

Step 4: Update ui.config Filter

Update 

ui.config/src/main/content/META-INF/vault/filter.xml
:

 

<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
    <filter root="/apps/wknd/osgiconfig"/>
</workspaceFilter>
 

Step 5: Deploy and Verify

  1. Build: 

    mvn clean install -PautoInstallPackage

     

  2. Check service user exists: Go to 

    /useradmin
     in AEM

     

  3. Verify permissions: Check that 

    workflow-service-user
     has access to 
    /content/dam

     

Root Cause of Your Issues

The console errors and missing folders are caused by:

  1. Wrong bundle name in service user mapping

  2. Missing service user with proper permissions

  3. Missing repository initialization script

This fix will resolve both the workflow execution and the AEM Sites display issues you're experiencing.