Expand my Community achievements bar.

Submissions are now open for the 2026 Adobe Experience Maker Awards.

Getting the list of un-registred namespace for assets

Avatar

Level 2

Background: We are trying to cleanup the DAM and there are som many assets that got migrated from elsewhere, from what i know Assets were literally dumped in the AEM DAM.

Task: We are trying to cleanup the DAM by moving very old and unused assets to a archive folder.

Issue: In order to do so we have used ACS commons Bulk Move Operation from the Renovator and also created a custom Asset Move operation using Granite Asset API. 
[1]. ACS commons - Shows the successful Dry run and breaks in between due to some NameSpace not existing issue. and dose not updates what assets got moved - which leads again a manual process to do this activity.
[2]. Cannot Use OOTB move operations as we have more than 20k assets from different location.
3. Created a Custom Move Operation which uses the features and overcomes the drawback of [1] and [2]. Provides the report of the assets that did not move and dose not break the job in between if any asset failed to move.

Question: My question here is I can optimize this custom solution more by identifying the assets that have non existing namespace in AEM and probably delete them from the source location without moving them around or create a list of those assets. 

The Most Important question here is how to analyse any asset if they have non-existing namespace also I don't have the list of non-existing namespaces so that we should not rely on the predefined list.

Please provide your valuable insights on this. 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

3 Replies

Avatar

Level 10

hi @kr_Saurabh1707,

I cannot think of anything quick and out of the box. Here's what I would do.

 

First get the list of namespaces:

Screenshot 2025-05-29 at 10.03.02.png

Next, I would create a package to download all asset metadata (excluding renditions) using the following filter settings:

Root path: /content/dam/your/root
Rules: Exclude=.*/renditions/.*

 

After extracting the package contents, run the following bash command to find all used namespaces:

grep -R -e "[a-zA-Z0-9]*:[a-zA-Z0-9]*=" | cut -d: -f2 | sed -e 's/^[[:space:]]*//' | grep -v "<" | grep -v Binary | sort -u

Result:

cq
crs
dam
dc
exif
exifEX
Iptc4xmpCore
jcr
photoshop
psAux
sling
stEvt
stRef
tiff
xmp
xmpMM
xmpRights

 

To identify missing namespaces, compare the list of used namespaces with all available namespaces in your instance, found under “/jcr:system/rep:namespaces”. You can then execute a command to find assets with the missing namespaces.

grep -R xmp:

The command will return both the path and the property's key-value pair.

./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_2.jpg/.content.xml:            xmp:CreateDate="{Date}2015-07-22T11:47:36.000-07:00"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_2.jpg/.content.xml:            xmp:CreatorTool="Adobe Photoshop CC 2015 (Macintosh)"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_2.jpg/.content.xml:            xmp:MetadataDate="{Date}2016-01-17T11:33:08.000-05:00"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_2.jpg/.content.xml:            xmp:ModifyDate="{Date}2016-01-17T11:33:08.000+01:00"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_4.jpg/.content.xml:            xmp:CreateDate="{Date}2015-07-22T11:48:48.000-07:00"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_4.jpg/.content.xml:            xmp:CreatorTool="Adobe Photoshop CC 2015 (Macintosh)"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_4.jpg/.content.xml:            xmp:MetadataDate="{Date}2016-01-14T10:58:11.000-08:00"
./jcr_root/content/dam/we-retail/en/activities/hiking/hiking_4.jpg/.content.xml:            xmp:ModifyDate="{Date}2016-01-14T10:58:11.000+01:00"

This can be easily converted into a CSV file to be used as input. Now, you can create a custom workflow step that processes each CSV entry by deleting the property with the missing namespace from the asset.

Excerpt code to delete a property (AI generated):

    /**
     * Deletes a specified property from a JCR node.
     *
     * @param resourceResolver The ResourceResolver instance to access the JCR.
     * @param nodePath         The JCR path to the node (e.g., "/content/dam/myasset/jcr:content/metadata").
     * @param propertyName     The name of the property to delete (e.g., "my:customProperty").
     * @return true if the property was found and deleted, false otherwise.
     */
    public boolean deleteProperty(ResourceResolver resourceResolver, String nodePath, String propertyName) {
        if (resourceResolver == null || nodePath == null || propertyName == null || nodePath.isEmpty() || propertyName.isEmpty()) {
            LOG.warn("Invalid input: resourceResolver, nodePath, or propertyName cannot be null or empty.");
            return false;
        }

        Session session = null;
        try {
            // 1. Adapt ResourceResolver to JCR Session
            session = resourceResolver.adaptTo(Session.class);
            if (session == null) {
                LOG.error("Could not adapt ResourceResolver to JCR Session.");
                return false;
            }

            // 2. Check if the node exists
            if (!session.nodeExists(nodePath)) {
                LOG.warn("Node does not exist at path: {}", nodePath);
                return false;
            }

            // 3. Get the Node
            Node node = session.getNode(nodePath);

            // 4. Check if the property exists on the node
            if (!node.hasProperty(propertyName)) {
                LOG.info("Property '{}' does not exist on node '{}'. No action taken.", propertyName, nodePath);
                return false;
            }

            // 5. Delete the property
            node.getProperty(propertyName).remove();
            LOG.debug("Attempting to remove property '{}' from node '{}'.", propertyName, nodePath);

            // 6. Save the changes to the repository
            session.save();
            LOG.info("Successfully deleted property '{}' from node '{}'.", propertyName, nodePath);
            return true;

        } catch (RepositoryException e) {
            LOG.error("RepositoryException occurred while deleting property '{}' from node '{}': {}",
                    propertyName, nodePath, e.getMessage(), e);
            // In case of an error, it's good practice to revert pending changes
            if (session != null && session.hasPendingChanges()) {
                try {
                    session.refresh(false); // Discard all pending changes
                    LOG.info("Discarded pending changes due to error.");
                } catch (RepositoryException refreshEx) {
                    LOG.error("Error refreshing session after deletion failure: {}", refreshEx.getMessage(), refreshEx);
                }
            }
            return false;
        } finally {
            // 7. Close the ResourceResolver (and indirectly the Session)
            // If the ResourceResolver was obtained for this specific operation, close it.
            // If it was passed from an external service that manages its lifecycle, do not close it here.
            // For most Sling services, you'd want to close the resolver when you're done with it.
            if (resourceResolver != null && resourceResolver.isLive()) {
                // The ResourceResolver.close() will also close the associated JCR Session
                resourceResolver.close();
                LOG.debug("ResourceResolver closed.");
            }
        }
    }

 

Avatar

Community Advisor

Hi @kr_Saurabh1707 ,

Try below steps:

Step 1: Get the List of Registered Namespaces in AEM

Use CRXDE or JCR Explorer:

Path:

/jcr:system/rep:namespaces

Each namespace appears like:

<ns:dc xmlns:ns="http://www.jcp.org/jcr/1.0">dc</ns:dc>
<ns:dam xmlns:ns="http://www.adobe.com/dam/1.0">dam</ns:dam>

Export this to a valid-namespaces.txt file.

 

comm -23 used-namespaces.txt valid-namespaces.txt > missing-namespaces.txt

This gives you the unregistered / unknown namespaces used in DAM assets.

 

Step 5: Identify Assets with Unregistered Namespaces

You can now build a report via Java:

Java Logic (in a workflow or service)

public List<String> findAssetsWithInvalidNamespaces(ResourceResolver resolver, Set<String> invalidNamespaces) {
    List<String> invalidAssets = new ArrayList<>();
    Iterator<Resource> assets = resolver.findResources("SELECT * FROM [dam:Asset]", Query.JCR_SQL2);
    
    while (assets.hasNext()) {
        Resource asset = assets.next();
        Resource metadata = asset.getChild("jcr:content/metadata");
        if (metadata != null) {
            ValueMap vm = metadata.getValueMap();
            for (String key : vm.keySet()) {
                if (key.contains(":")) {
                    String ns = key.split(":")[0];
                    if (invalidNamespaces.contains(ns)) {
                        invalidAssets.add(asset.getPath());
                        break; // Skip after first invalid namespace found
                    }
                }
            }
        }
    }
    return invalidAssets;
}
Spoiler

Step 6: Clean or Report

Now that you have the list of invalid assets:

Generate CSV report for manual review

Or automate deletion of invalid properties:

if (node.hasProperty("invalid:property")) {
    node.getProperty("invalid:property").remove();
}

Or skip assets altogether during your custom bulk move logic.

Regards,
Amit

 

Avatar

Administrator

@kr_Saurabh1707 

Just checking in — were you able to resolve your issue?
We’d love to hear how things worked out. If the suggestions above helped, marking a response as correct can guide others with similar questions. And if you found another solution, feel free to share it — your insights could really benefit the community. Thanks again for being part of the conversation!



Kautuk Sahni