Dynamic Media is one of the versatile tools provided by Adobe. Previously, it was known as Scene7. It has strong Asset editing and authoring tools capabilities. It is based on a Cache delivery network, which loads the contents to improve page load time and renders the right image renditions correctly resized and optimized. Dynamic Media allows requesting devices to request exactly what type of rendition, version, and exact image size is needed by that device at the moment of request.
Have you wondered about the benefits of integrating the Dynamic Media feature in custom components? In this blog, I will demonstrate how to integrate Dynamic Media with custom components and the benefits it provides by doing so.
When we integrate dynamic media with AEM, it enables various Dynamic Media functionalities like image/video profiles, DM metadata, DM workflows, and some set of out-of-the-box Dynamic Media Components. Also, some core components like Image provide Dynamic Media functionality.
If you have not integrated Dynamic Media with AEM, please go through the documentation provided by Adobe on how to Configure the Dynamic Media for AEM.
Loading Dynamic Media Library
First, we need to load dynamic media clientlibs on every page to render Dynamic Media Assets through AEM Components.
Paste the following code into the head section page component i.e. customheaderlibs.html
<!--/* Dynamic Media Integration */--> <sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-call="${clientLib.all @ categories='cq.dam.components.scene7.dynamicmedia,cq.dam.components.scene7.common.i18n'}"></sly>
Custom Sling Model Implementation
Then create one custom sling model common utility for reading Dynamic Media assets metadata properties which is required to load any AEM assets through dynamic media functionality.
Sling model Implementation
public interface DynamicMedia extends BaseModel { String getCurrentPagePath(); String getPageLocale(); String getAssetName(); String getAssetPath(); String getDynamicMediaViewerPath(); String getDynamicMediaImageServerPath(); boolean isWcmModeDisabled(); @Slf4j @Model( adaptables = SlingHttpServletRequest.class, adapters = DynamicMedia.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL ) public class DynamicMediaImpl implements DynamicMedia { private static final String DM_IMAGE_SERVER_PATH = "is/image/"; private static final String DM_VIEWERS_SERVER_PATH = "s7viewers/"; @SlingObject private SlingHttpServletRequest request; @ScriptVariable private Page currentPage; @RequestAttribute private String imageReference; @Getter private String assetName; @Getter private String assetPath; @Getter private String dynamicMediaViewerPath; @Getter private String dynamicMediaImageServerPath; @PostConstruct protected void init() { if (StringUtils.isNotEmpty(imageReference)) { final Resource assetResource = request.getResourceResolver() .getResource(imageReference); if (assetResource != null) { final Asset asset = assetResource.adaptTo(Asset.class); if (asset != null) { this.id = getId() + "-" + asset.getID(); assetName = asset.getName(); assetPath = asset.getMetadataValue(Scene7Constants.PN_S7_FILE); final String dynamicMediaServer = asset.getMetadataValue( Scene7Constants.PN_S7_DOMAIN); dynamicMediaImageServerPath = dynamicMediaServer + DM_IMAGE_SERVER_PATH; dynamicMediaViewerPath = dynamicMediaServer + DM_VIEWERS_SERVER_PATH; } } } } @Override public String getCurrentPagePath() { return currentPage.getPath(); } @Override public String getPageLocale() { return LocaleUtils.generateLocaleFromPath(getCurrentPagePath()); } @Override public boolean isWcmModeDisabled() { return (WCMMode.fromRequest(request) == WCMMode.DISABLED); } }
Once we are done with the Sling model implementation part then create one HTL template inside directory /apps/<Project Driectory>/components/atoms/dynamicmedia/image.html to provide reusability within the component whenever we want to load any image using dynamic media for a specific component. Paste the following code in the image.html file.
<sly data-sly-template.dynamicMediaImageTemplate="${ @ imageReference, aspectRatio, altText, suffixId}"> <div data-sly-use.dynamicMediaImage="${'com.perficientblogs.core.models.commons.DynamicMediaModel' @ imageReference = imageReference}" id="${suffixId || dynamicMediaImage.id}" data-current-page="${dynamicMediaImage.currentPagePath}" data-page-locale="${dynamicMediaImage.pageLocale}" data-asset-path="${dynamicMediaImage.assetPath}" data-asset-name="${dynamicMediaImage.assetName}" data-asset-type="image" data-viewer-path="${dynamicMediaImage.dynamicMediaViewerPath}" data-imageserver="${dynamicMediaImage.dynamicMediaImageServerPath}" data-wcmdisabled="${dynamicMediaImage.wcmModeDisabled}" data-dms7="" data-mode="smartcrop" //Note: We can set the image preset mode here data-enablehd="always" data-aspectratio="${aspectRatio @context='scriptString'}" data-title="${altText}" data-alt="${altText}" class="s7dm-dynamic-media"> </div> </sly>
Now refer to this HTL template file anywhere in the component HTML where we want to load any authored Image through dynamic media CDN.
<sly data-sly-use.image=" /apps/<Project Driectory>/components/atoms/dynamicmedia/image.html" data-sly-call="${image.dynamicMediaImageTemplate @ imageReference= modeloject.fileReference, aspectRatio= false, altText= 'Hello world Component'}"></sly>
Make sure to pass a value for imageReference property which is mandatory. We can also pass the values with other objects named aspectRatio, altText as per the need or extend the functionality as per the requirement.
See the image above for the final output. Look at the URL of the image rendered by the custom component. It is delivered from Dynamic Media provided CDN. That is the benefit you achieve with this. This way the images will be served much faster to the user based on the region they are in.
If you have any questions or comments, drop them in the chat below!
Hi,
Thank you for sharing the content. I’m trying to intergrate it to all my custom components.
May I know what does the getPageLocale return from the LocaleUtils? And also what’s within the BaseModel?