Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session
SOLVED

Creating Content Fragments Programmatically (Best Practice)?

Avatar

Level 3

Hey all,

 

I'm working on a service will take data from an API &, in theory, write what is returned to a list of content fragments. I've gotten pretty far along, but I'm wondering if there's a better / cleaner way than my current approach. 

 

Right now I have a function createContentFragment (seen below) which takes in a fullBranch object (data I want to turn into a content fragment), parentResource (self explanatory) and templateResource (template of the content fragment I want to turn this data into).

I noticed in the ContentFragment class that there's not a "setValues" or "setValue"  function... it seems from the documentation that I would need to iterate over each contentElement & set each value individually. Obviously this is pretty annoying, so wondering if anyone has any suggestions on how to better / more easily set the ContentElement values than my intended approach? I also have a Store model (separate from the templateResource for now) which I was thinking I could possibly connect to the content fragment somehow? Not sure if this is possible. Any help is much appreciated!

 

    private void createContentFragment(FullBranch fullBranch, Resource parentResource, Resource templateResource) {
        try {
            FragmentTemplate tpl = templateResource.adaptTo(FragmentTemplate.class);
            if (tpl != null) {
                ContentFragment newFragment = tpl.createFragment(parentResource, fullBranch.getKey(), fullBranch.getName());

                Iterator < ContentElement > contentElement = newFragment.getElements();
                //current long winded approach
                while (contentElement.hasNext()) {
                    ContentElement contentElementObject = contentElement.next();
                    FragmentData value = contentElementObject.getValue();
                    String FieldName = contentElementObject.getName();
                    //would have to get the value from fullBranch using the FieldName and another function w/ a switch statement
                    value.setValue("test");
                    contentElementObject.setValue(value);

                }
            }
            ObjectMapper().writeValueAsString(fullBranch));
    } catch (Exception ex) {
        LOGGER.error("Something went wrong" + ex.getMessage());
    }
    }
1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Please find the some of the same code below.

 Resource fragmentResource = resourceResolver.getResource(fragmentPath);
        if (null != fragmentResource) {
            ContentFragment contentFragment = fragmentResource.adaptTo(ContentFragment.class);
            if (null != contentFragment) {
                Iterator<ContentElement> elements = contentFragment.getElements();
                while (elements.hasNext()) {
                    ContentElement contentElement = elements.next();
                    if (contentElement.getValue().getDataType().isMultiValue()) {
                        String[] values = contentElement.getValue().getValue(String[].class);
                        String value = null;
    
                        if (values != null) {
                            value = StringUtils.join(values, CommonConstants.CHAR_COMMA);
                            cfElements.put(contentElement.getName(), value);
                        }
    
                    } else {
                        cfElements.put(contentElement.getName(), contentElement.getContent());
                    }
                }
            }
        }

 

Also check below thread for creating CFs.

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/programmatically-create-a-...

 

View solution in original post

4 Replies

Avatar

Level 3

Thanks for the reply, I followed the first link's guidelines, but was more wondering if it was possible to map a Model to the content fragment (i.e. use setters from that model to fill in data)... the second link you sent I believe references fragmentManager.create() which I think is a deprecated function in newer versions of AEM

Avatar

Correct answer by
Community Advisor

Please find the some of the same code below.

 Resource fragmentResource = resourceResolver.getResource(fragmentPath);
        if (null != fragmentResource) {
            ContentFragment contentFragment = fragmentResource.adaptTo(ContentFragment.class);
            if (null != contentFragment) {
                Iterator<ContentElement> elements = contentFragment.getElements();
                while (elements.hasNext()) {
                    ContentElement contentElement = elements.next();
                    if (contentElement.getValue().getDataType().isMultiValue()) {
                        String[] values = contentElement.getValue().getValue(String[].class);
                        String value = null;
    
                        if (values != null) {
                            value = StringUtils.join(values, CommonConstants.CHAR_COMMA);
                            cfElements.put(contentElement.getName(), value);
                        }
    
                    } else {
                        cfElements.put(contentElement.getName(), contentElement.getContent());
                    }
                }
            }
        }

 

Also check below thread for creating CFs.

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/programmatically-create-a-...

 

Avatar

Level 7

any example to unit test 

contentElement.getValue().getValue(String[].class);

I am getting io.wcm unsupported operation exception, when trying to unit test this specific line of code.