Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.

Optimising Content Fragment And Variation Creation

Avatar

Level 1

Hi

Currently we have code to programmatically create a content fragment with variations.

The process is:

1. create content fragment

2. create content fragment variation and populate all the variation elements by calling the createVariation method below:

 

public static void createVariation(ContentFragment cf, JsonObject dp, String variationName, String variationTitle) throws ContentFragmentException, PersistenceException {
VariationTemplate vt = cf.createVariation(variationName, variationTitle, "");
Iterator<ContentElement> itr = cf.getElements();

while(itr.hasNext()) {
ContentElement cfElement = itr.next();
ContentVariation cv = cfElement.getVariation(vt.getName());
cv.setContent(dp.getString(cfElement.getName(), ""), "String");
}
}

We found that this code is slow and cumbersome.  We would like to create a content fragment and its variations in one method call like https://experienceleague.adobe.com/docs/experience-manager-65/assets/extending/assets-api-content-fr...

but we don't want to be using a HTTP POST to do it. Is there AEM library we can use to do the same? com.adobe.cq.dam.cfm.ContentFragment package seems a bit limited for what we need.

3 Replies

Avatar

Community Advisor

@deve71507918 gr8 that you reached out to AEM communities.

 

I don't think we have any such method OOTB, but even if it is, that OOTB method also have to create CF first then its variation, so I would recommend instead to see if you can further optimize your code? For one such usecase I have seen some code having more than one session.save calls in one transaction, almost after every chunk of code and when we optimized it once per transaction, resulted varied.

 

And when you said slow, what is your trigger point for this? Are you expecting any SLA for this? Are you creating CFs in loop?

Avatar

Employee Advisor

@deve71507918 
Can you please elaborate why are we iterating all the Content Fragment Elements in above code snippet. If the purpose of this method is to just create or update a variation on a Content Fragment, there is no need to traverse all the CF elements, instead just get a list of all the variations listAllVariations(), iterate to find if the xyz variation already exist, then update it with new description, if it does not exist add a new variation xyz with the description.

 

Also you might want to look into below development guidelines and caveats for further optimization:

https://experienceleague.adobe.com/docs/experience-manager-65/developing/extending-aem/customizing-c...

 

Avatar

Level 1

@Shashi_Mulugu @krati_garg 

Thanks for your inputs.

Our code creates content fragments and their variations and then populates their element values. If I call .listAllVariations() and get the variationDefinition, I will still need to call getElements as it's not the title/description of the variation I want to update but its element values.  Further more, we only really call one commit at the end of the process.

I've re-written the code and added timings and comments:

public static void createVariationNew(ContentFragment cf, JsonObject dp, String variationName, String variationTitle, Logger log) throws ContentFragmentException, PersistenceException, RepositoryException {
long startTime = System.currentTimeMillis();
//create the variation
cf.createVariation(variationName, variationTitle, "");

Resource cfResource = cf.adaptTo(Resource.class);
Resource variationResource = cfResource.getChild(JcrConstants.JCR_CONTENT + "/data/" + variationName);
Node variationNode = variationResource.adaptTo(Node.class);
// now populate each element with the values I want to seed it with.
for (String element: dp.keySet()){
variationNode.setProperty(element, dp.getString(element, ""));
}
log.debug("Time to create NEW {}: {}", variationName.substring(0,variationName.indexOf("-")), (System.currentTimeMillis() - startTime));
}

public static void createVariationOld(ContentFragment cf, JsonObject dp, String variationName, String variationTitle, Logger log) throws ContentFragmentException, PersistenceException {
long startTime = System.currentTimeMillis();
//create the variation
VariationTemplate vt = cf.createVariation(variationName, variationTitle, "");
//get all elements for that variation
Iterator<ContentElement> itr = cf.getElements();
//for each element
while(itr.hasNext()) {
ContentElement cfElement = itr.next();
//grab the variation for that element - but i already have my variation from cf.createVariation
ContentVariation cv = cfElement.getVariation(vt.getName());
//now update the element value for that variation
cv.setContent(dp.getString(cfElement.getName(), ""), "String");
}
log.debug("Time to create OLD {}: {}", variationName.substring(0,variationName.indexOf("-")), (System.currentTimeMillis() - startTime));
}

Toggling between createVariatonOld and createVariationNew gives me the following outcomes:

 

deve71507918_0-1667533831879.png

If I use com.adobe.cq.dam.cfm.ContentFragment.getElements and com.adobe.cq.dam.cfm.ContentVariation.getVariation the time taken doubles compared to using javax.jcr.Node.setProperty.  The other time consuming call is com.adobe.cq.dam.cfm.ContentFragment.createVariation.  I probably could reduce the time by using javax.jcr.Node to create the required variation nodes but am hesitant as that one call seems to create /model/variations/myVariation node as well as the /data/myVariation.  

 

In the documentation com.adobe.cq.dam.cfm.ContentFragment is the recommended way of creating content fragment variaitons but why is it less efficient that using just javax.jcr.Node.setProperty?