Suren Konathala
Suren Konathala

Reputation: 3597

How to retrieve all properties of an asset using the QueryBuilder Api

When i use the below query on AEM QueryDebug

path=/content/dam/we-retail  
type=dam:Asset  
p.limit=-1  
p.nodedepth=2  
p.hits=full  
p.guesstotal=true 

And the formed URL/JSON QueryBuilder link.

I can see all the properties for each asset including jcr:content, metadata as below:

enter image description here

I need to return the same result to service/endpoint i'm building on AEM for a customer. When I translate the same above query into Query builder API

queryParamsMap.put("type", "dam:Asset");  
queryParamsMap.put("p.limit", "-1");  
queryParamsMap.put("p.nodedepth", "2");  
queryParamsMap.put("p.hits", "full");  
queryParamsMap.put("p.guessTotal", "true");  

How can i retrieve all the values?

SearchResult result = query.getResult();  
for (final Hit hit : result.getHits()) {  
  Resource resource = hit.getResource();  
  Asset asset = resource.adaptTo(Asset.class);  

If i use asset.getMetadata(), we can see only the properties under jcr:content\metadata but not the other properties.

and

if i use ValueMap properties = resource.getValueMap(); we can retrieve all the asset properties (like jcr:path, jcr:primaryType etc) but not "metadata".

Is there any way to get all the values for an Asset node?

Upvotes: 0

Views: 7817

Answers (2)

julianhs
julianhs

Reputation: 46

Another way to get all the properties of an AEM asset from the dam:Asset node itself to the metadata node (jcr:content/metadata) is using Apache Sling Models and adapting each resource returned by your query to this model.

For example:

@Model(adaptables=Resource.class)
public class MyAsset{

    @Inject
    @Named("jcr:created")
    private String createdDate;

    @Inject
    @Named("jcr:createdBy")
    private String createdBy;

    @Inject
    @Named("jcr:content/jcr:lastModified")
    @Optional
    private String lastModified;

    @Inject
    @Named("jcr:content/metadata/dc:title")
    @Optional
    private String title;

    @Inject
    @Named("jcr:content/metadata/dc:description")
    @Optional
    private String description;

    @PostConstruct
    protected void init() {
         // You can code here any task needed to be executed after all the injections of the model are done
    }

  //getters and setters...

}

Note that you can specify any property of any descendant node of the resource using the annotation @Named.

I will suggest you use this approach if you need specific and few properties of the resource. If you need all properties I think the approach you found is better because you do not need to create a model to maintain all properties.

Using the model the final code will be:

for (Hit hit : result.getHits()) {
      Resource resource = hit.getResource();
        if(resource!=null){
         MyAsset myAsset = resource.adaptTo(MyAsset.class);
        Logger.info("The asset {} was modified on {}", myAsset.getTitle(), myAsset.getLastModified());
        }
    }

For more info about Sling Model you can refer to:

https://sling.apache.org/documentation/bundles/models.html

Upvotes: 1

Suren Konathala
Suren Konathala

Reputation: 3597

After some research, i found the below solution. Posting here for others reference.

As mentioned by @Imran-Saeed , there is no method that will return all the properties of an Asset (or a Node. Asset is also a node) in AEM. We have to do this in a combination.

  1. Get all the top level properties (Node root level). These include jcr:created, jcr:createdBy, etc.
  2. Get all jcr:content level properties. These include cq:name, cq:lastModified, etc
  3. Get all jcr:content\metadata level properties. These include dc:title, any custom metadata etc.
  4. You can add all these to another new ValueMap that can hold all the properties of a particular Node/Asset.

enter image description here

Below is a code snippet:

Resource resource;
ValueMap mainProperties;
ValueMap assetMetadataProperties;
Resource metadataResource;
ValueMap jcrProperties;
Resource jcrdataResource;
ValueMap allProperties;

for (Hit hit : result.getHits()) {
        //LOGGER.info("\n********Hit path="+hit.getPath()+", title="+hit.getTitle());
        resource = hit.getResource();

        if(null!=resource){
            mainProperties = resource.getValueMap();

            // Add JCR Properties
            jcrdataResource = resource.getChild("jcr:content");
            jcrProperties = ResourceUtil.getValueMap(jcrdataResource);

            // Add Metadata properties
            metadataResource = resource.getChild("jcr:content/metadata");
            assetMetadataProperties = ResourceUtil.getValueMap(metadataResource);

            // Adding all togethe
            allProperties = new ValueMapDecorator(new HashMap());
            allProperties.putAll(hit.getProperties());
            allProperties.putAll(mainProperties); // Includes jcr:created createdDate etc.
            allProperties.put("jcr:path",hit.getPath()); //Add Path
            allProperties.putAll(jcrProperties);
            allProperties.putAll(assetMetadataProperties);

            //LOGGER.debug("All Asset Properties="+new Gson().toJson(allProperties));               
        }
    }

Note

  1. jcr:path is not returned by any of the above. So i had to explicitly add it using hit.getPath
  2. The name of the node or Asset name can be pulled from hit.getTitle(). Ofcourse this is also returned as part of cq:name.
  3. There are other ways to get the properties as well. One aother way is to get the Node and retrieve the properties. com.day.cq.search.result.Hit has a method getNode() that returns a java.jcr.Node interface and you can use that get to fetch the properties.

Upvotes: 1

Related Questions