0
votes

I help oversee (quality assurance) a website on AEM that has around 65,000 pages, 320,000 assets, and about 300 users able post and make changes. One thing that has been extremely helpful is a script a former IT employee wrote for us that used the querybuilder servlet to make queries and pull full lists of pages and assets. I've been able to take this output and build all sorts of automated reports using it.

The one thing I have not been able to figure out is how to find out if an asset or page is referenced by another page. The main thing I care about is just a simple true/false on if it is refereced or not. Ideally I would like it if it could be in the initial query and not have to do a query for each individual asset, but if that is the only way then I guess it in theory could be acceptable.

Just a sample query I could run currently to get some info on assets (I limited this one to 5 results for the sample):

http://localhost:4502/bin/querybuilder.json?p.hits=selective&p.offset=0&p.limit=5&p.properties=jcr%3acontent%2fmetadata%2fdc%3aformat%20jcr%3acontent%2fmetadata%2fdc%3atitle%20jcr%3apath%20&path=%2fcontent%2fdam&type=dam%3aAsset

Is there any way to add to that a field for if it is referenced? Or an array of all the references to it?

We are currently running AEM 6.2 but will soon be upgrading to 6.4.

Thank you!

2

2 Answers

0
votes

There is an OOTB servlet that will return the list of pages that refer to a particular page or asset

To check if a page or asset is referenced, use

https://localhost:4502/bin/wcm/references?
_charset_=utf-8
&path=<path of the page>
&predicate=wcmcontent
&exact=false

The output will be a json response containing an array of references of the name 'pages'. If the page is not referenced it will be an empty array.

This servlet uses ReferenceSearch API the other answer mentions. If you need this value as JSON outside of AEM, you can straight away use the OOTB one without having to write your own servlet.

1
votes

For your requirement, you can leverage the AssetReferenceSearch API which can give the details of Assets used in a page (node of type cq:Page).

You can use the following code to accomplish your task -

package org.redquark.aem.assets.core;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.jcr.Node;
import javax.servlet.Servlet;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.commons.util.AssetReferenceSearch;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * @author Anirudh Sharma
 *
 */
@Component(
        service = Servlet.class, 
        property = { 
                "sling.servlet.methods=GET", 
                "sling.servlet.resourceTypes=cq/Page",
                "sling.servlet.selectors=assetreferences", 
                "sling.servlet.extensions=json", 
                "service.ranking=1000" 
                }
        )
public class FindReferencedAssetsServlet extends SlingSafeMethodsServlet {

    // Generated serial version UID
    private static final long serialVersionUID = 8446564170082865006L;

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private static final String DAM_ROOT = "/content/dam";

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {

        response.setContentType("application/json");

        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        try {

            // Get the current node reference from the resource object
            Node currentNode = request.getResource().adaptTo(Node.class);

            if (currentNode == null) {
                // Every adaptTo() can return null, so let's handle the case here
                // However, it is very unlikely
                log.error("Cannot adapt resource {} to a node", request.getResource().getPath());
                response.getOutputStream().print(new Gson().toString());

                return;
            }

            // Using AssetReferenceSearch which will do all the work for us
            AssetReferenceSearch assetReferenceSearch = new AssetReferenceSearch(currentNode, DAM_ROOT,
                    request.getResourceResolver());

            Map<String, Asset> result = assetReferenceSearch.search();

            List<AssetDetails> assetList = new LinkedList<>();

            for (String key : result.keySet()) {

                Asset asset = result.get(key);

                AssetDetails assetDetails = new AssetDetails(asset.getName(), asset.getPath(), asset.getMimeType());

                assetList.add(assetDetails);
            }

            String jsonOutput = gson.toJson(assetList);

            response.getOutputStream().println(jsonOutput);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }
}

The corresponding AssetDetails model class is as follows -

package org.redquark.aem.assets.core;

/**
 * @author Anirudh Sharma
 */
public class AssetDetails {

    private String name;
    private String path;
    private String mimeType;

    /**
     * @param name
     * @param path
     * @param mimeType
     */
    public AssetDetails(String name, String path, String mimeType) {
        this.name = name;
        this.path = path;
        this.mimeType = mimeType;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the path
     */
    public String getPath() {
        return path;
    }

    /**
     * @param path the path to set
     */
    public void setPath(String path) {
        this.path = path;
    }

    /**
     * @return the mimeType
     */
    public String getMimeType() {
        return mimeType;
    }

    /**
     * @param mimeType the mimeType to set
     */
    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }
}

Now, you can invoke this servlet by the following request -

http://localhost:4502/content/we-retail/language-masters/en/men.assetreferences.json.

This will give output in the following format

[
  {
    "name": "running-trail-man.jpg",
    "path": "/content/dam/we-retail/en/activities/running/running-trail-man.jpg",
    "mimeType": "image/jpeg"
  },
  {
    "name": "enduro-trail-jump.jpg",
    "path": "/content/dam/we-retail/en/activities/biking/enduro-trail-jump.jpg",
    "mimeType": "image/jpeg"
  },
  {
    "name": "indoor-practicing.jpg",
    "path": "/content/dam/we-retail/en/activities/climbing/indoor-practicing.jpg",
    "mimeType": "image/jpeg"
  }
]

You can edit the AssetDetails class as per your requirement.

I hope this helps. Happy Coding!!!