Have you faced issue of design dialog configurations being overwritten by deployment?
Starting AEM 6.1, AEM provides ability to avoid design configuration overwrite, by extracting configurations from /etc to /conf.
Example:
Lets consider a scenario where business had requested a default title ‘Contact Us’ for a component. Few months later, they change the title to ‘Contact with us’ via Design Dialog.
Your development team is working on second version of the Contact Us component, to add a new field for Email ID with default value ‘contactus@adobe.com’
Once completed, the team deploys the second version of component with default value of email ID. Result would be “Design configuration ‘Contact with us’ configured by business, is restored to old value ‘Contact Us'”
Resolution through /conf to fix design configuration overwrite
- Use mode=”merge” in filter.xml for deploying design. This would ensure that on deployment existing nodes are not deleted. For more details refer to link
- <filter root=”/etc/designs/<app_name>/jcr:content” mode=”merge”/>
- Configure default values in /conf: Sling Models can then be used to resolved values in required preference order. Example: Edit -> Design -> Default (from /conf path)
Steps to configure default values in /conf
Step 1: Define Configurations
In this step, we create a suitable configuration hierarchy considering rules described below. Also, add required default configurations in the jcr:content nodes.
In the above image, we can observe that configuration hierarchy should have:
- ‘sling:Folder’ structure below ‘/conf’ to define the site/app that the configurations belong to.
- ‘settings’ of type ‘sling:Folder’ which holds all the configurations.
- Configuration nodes below ‘setting’ of type ‘cq:Page’
- Configuration properties in ‘jcr:content’ of configuration nodes
Step 2: Add cq:conf property to the root of the project.
type: String
value: Site’s configuration path
Step 3: Provide read permission to the target users & authors on:
- Site configuration node under /conf
- Root node of the site where cq:conf is configured.
Step 4: Use a Sling Model to derive the values in the required order (edit, design, conf).
There are 2 APIs that could be utilized:
- com.adobe.granite.confmgr.Conf resolves the configuration from currentPage
- com.adobe.granite.confmgr.ConfMgr resolves the configuration from resource.
Fetch default configuration via com.adobe.granite.confmgr.Conf
import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.Model; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.adobe.granite.confmgr.Conf; import com.day.cq.wcm.api.NameConstants; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.designer.Style; @Model(adaptables = SlingHttpServletRequest.class) public class ContactUsModel { private static final Logger LOG = LoggerFactory.getLogger(ContactUsModel.class); @Inject private Page currentPage; private ValueMap contactUsSettings; @Inject private Style currentStyle; @PostConstruct protected void init() { Conf conf = currentPage.adaptTo(Conf.class); if(conf==null){ LOG.warn("Configurations not found for: " + currentPage.getPath()); } else { String templatePath = currentPage.getProperties().get(NameConstants.NN_TEMPLATE, ""); contactUsSettings = conf.getItem(templatePath+"/contactUsComponent"); } } public String getDesignTitle() { /* * Return title in following preference order: * 1. Title from Design * 2. Title from conf */ String designTitle = currentStyle.get("title", ""); if(StringUtils.isEmpty(designTitle)){ //Title not configured in Design. Fetching from /conf LOG.debug("Fetching default title from /conf"); return contactUsSettings.get("contactUsTitle", ""); } else { //Title configured in Design. LOG.debug("Title configured in design dialog: " + designTitle); return designTitle; } } }
Fetch default configuration via com.adobe.granite.confmgr.ConfMgr
import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.Model; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.adobe.granite.confmgr.Conf; import com.adobe.granite.confmgr.ConfMgr; @Model(adaptables = SlingHttpServletRequest.class) public class ContactUsModel { private static final Logger LOG = LoggerFactory.getLogger(ContactUsModel.class); @Inject private ConfMgr confMgr; @Inject private Resource currentResource; private ValueMap contactUsSettings; @PostConstruct protected void init() { final Conf conf = confMgr.getConf(currentResource); if(conf==null){ LOG.warn("Configurations not found for: " + currentResource.getPath()); } else { contactUsSettings = conf.getItem("/conf/techrevel/settings/apps/confEx/templates/someTemplate/contactUsComponent"); } } public String getTitle() { LOG.debug("Fetching default title from /conf"); return contactUsSettings.get("contactUsTitle", ""); } }
For more details, please refer to link