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.
Solved! Go to Solution.
Views
Replies
Total Likes
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:
Update your
ui.config
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
aem-guides-wknd.core
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" ] }
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 } } }
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>
Build:
mvn clean install -PautoInstallPackage
Check service user exists: Go to
/useradmin
Verify permissions: Check that
workflow-service-user
/content/dam
The console errors and missing folders are caused by:
Wrong bundle name in service user mapping
Missing service user with proper permissions
Missing repository initialization script
This fix will resolve both the workflow execution and the AEM Sites display issues you're experiencing.
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
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
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();
Views
Replies
Total Likes
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?
Views
Replies
Total Likes
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:
Update your
ui.config
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
aem-guides-wknd.core
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" ] }
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 } } }
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>
Build:
mvn clean install -PautoInstallPackage
Check service user exists: Go to
/useradmin
Verify permissions: Check that
workflow-service-user
/content/dam
The console errors and missing folders are caused by:
Wrong bundle name in service user mapping
Missing service user with proper permissions
Missing repository initialization script
This fix will resolve both the workflow execution and the AEM Sites display issues you're experiencing.