{"id":58732,"date":"2023-09-28T21:40:47","date_gmt":"2023-09-28T16:10:47","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=58732"},"modified":"2024-06-10T15:35:53","modified_gmt":"2024-06-10T10:05:53","slug":"context-aware-configuration-in-aem","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/context-aware-configuration-in-aem\/","title":{"rendered":"Context-aware configuration in AEM"},"content":{"rendered":"<h2><b>Use Case<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Imagine you have a special part on your website that shows different information based on where the website visitor is from. Let&#8217;s call it the &#8220;Location Info&#8221; part. This part is used in many places on the website, like different pages. Now, some places on the website have different needs \u2013 they want to show specific information based on where the visitor is located. For example, they might want to show different offers or messages depending on whether the visitor is in New York or Los Angeles.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, a unique challenge arises \u2013 the content of this component must adapt based on the geographical location of the user. This is where the power of context-aware configuration in AEM comes into play, facilitating the display of distinct configuration values for the same component on pages catering to different locations.<\/span><\/p>\n<h2><b>What is <\/b><b>Context-aware configuration<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">When building a multi-national website with AEM, you may need to use different configurations for different country-specific pages.\u00a0<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58729 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-1024x162.png\" alt=\"\" width=\"625\" height=\"99\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-1024x162.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-300x47.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-768x121.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-1536x243.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-2048x324.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image1-1-624x99.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">However, creating a separate configuration file for each country can be complex and error-prone. Instead, you can use the context-aware configuration feature in AEM to define one configuration class file with different configurations for multiple contexts. This approach simplifies your development process and reduces the risk of errors.<\/span><\/p>\n<h2><b>Steps for Implementation of Context-Aware Configuration<\/b><\/h2>\n<p>1. Context-aware configuration: <span style=\"font-weight: 400;\">To manage site-specific configurations, we can create a configuration class that defines configurations.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58728 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image2-1.png\" alt=\"\" width=\"850\" height=\"373\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image2-1.png 850w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image2-1-300x132.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image2-1-768x337.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image2-1-624x274.png 624w\" sizes=\"(max-width: 850px) 100vw, 850px\" \/><b>The @Configuration\u00a0 annotation is mandatory.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">In the configuration class, we can define a set of properties that specify the default configuration values.<\/span><\/p>\n<p><b>2. Using a model class to retrieve configurations<\/b><\/p>\n<p><span style=\"font-weight: 400;\">To use the Configuration class in our components, we need to create a model class that adapts to the configuration. <\/span><span style=\"font-weight: 400;\">Inside the Model class, we create a function that takes currentPage and ResourceResolver as Input.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58727 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1-1024x300.png\" alt=\"\" width=\"625\" height=\"183\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1-1024x300.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1-300x88.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1-768x225.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1-624x183.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image3-1.png 1227w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Context-aware configurations are built on top of context-aware resources. The same concept is used: configurations are named and the service to get them is the ConfigurationResolver. You can get a reference to the OSGi service <\/span><span style=\"font-weight: 400;\">org.apache.sling.caconfig.ConfigurationResolver<\/span><span style=\"font-weight: 400;\"> &#8211; It has a single method to get a ConfigurationBuilder. Alternatively, you can directly adapt your content resource directly to the ConfigurationBuilder interface and get the configuration:-<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58726 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-1024x176.png\" alt=\"\" width=\"625\" height=\"107\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-1024x176.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-300x52.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-768x132.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-1536x264.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-2048x353.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image4-1-624x107.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">The ConfigurationBuilder also supports getting the configurations as ValueMap or by adapting the configuration resources, e.g., to a Sling Model. In this case, we have to specify a configuration name that is otherwise derived automatically from the annotation class.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Internally, the ConfigurationResolver used the ConfigurationResourceResolver to get the configuration resources. It always uses the bucket name <\/span><span style=\"font-weight: 400;\">sling: configs<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Call that function by @PostConstruct annotation, where all variables get values from configuration.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58725 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-1024x182.png\" alt=\"\" width=\"625\" height=\"111\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-1024x182.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-300x53.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-768x137.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-1536x273.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5-624x111.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image5.png 2024w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><b style=\"font-size: 1rem;\">3. Create Component<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Inside the component, Model is used by data-sly-use and shows all values that it returns from Model on the page.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58724 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-1024x178.png\" alt=\"\" width=\"625\" height=\"109\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-1024x178.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-300x52.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-768x134.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-1536x268.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-2048x357.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image6-624x109.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><b style=\"font-size: 1rem;\">4. Create folders<\/b><span style=\"font-weight: 400;\"> for every content resource inside \/conf\/mysite.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58723 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image7.png\" alt=\"\" width=\"418\" height=\"394\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image7.png 418w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image7-300x283.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image7-24x24.png 24w\" sizes=\"(max-width: 418px) 100vw, 418px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">These folders are of jcr:primaryType = sling: folder.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For example:-<\/span><\/p>\n<p><span style=\"font-weight: 400;\">inside \/conf\/mysite ca,ca_b1,ca_bk are the folders of jcr:primaryType = sling:folder, and inside of these folders create folders sling:configs of the same type.<\/span><\/p>\n<p><b>5. Create a Configuration node.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Create a Configuration Node for every folder of jcr:primaryType = nt:unstructured.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58722 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image8.png\" alt=\"\" width=\"990\" height=\"366\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image8.png 990w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image8-300x111.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image8-768x284.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image8-624x231.png 624w\" sizes=\"(max-width: 990px) 100vw, 990px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">And define values for every node according to the context.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58721 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-1024x180.png\" alt=\"\" width=\"625\" height=\"110\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-1024x180.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-300x53.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-768x135.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-1536x271.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9-624x110.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image9.png 2044w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58720 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10-1024x246.png\" alt=\"\" width=\"625\" height=\"150\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10-1024x246.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10-300x72.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10-768x184.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10-624x150.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image10.png 1499w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58719 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-1024x191.png\" alt=\"\" width=\"625\" height=\"117\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-1024x191.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-300x56.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-768x143.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-1536x287.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11-624x116.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image11.png 1930w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><span style=\"font-size: 1rem;\"><strong>6.<\/strong> Inside \/content\/mysite under the specific site hierarchy, add property sling:configRef = [path of the folder that has a configuration for that specific site] in jcr: content.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58718 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image12.png\" alt=\"\" width=\"383\" height=\"538\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image12.png 383w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image12-214x300.png 214w\" sizes=\"(max-width: 383px) 100vw, 383px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">For example:-<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58717 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image13.png\" alt=\"\" width=\"807\" height=\"360\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image13.png 807w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image13-300x134.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image13-768x343.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image13-624x278.png 624w\" sizes=\"(max-width: 807px) 100vw, 807px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">When we use a component on any page, it takes configuration according to sling:configRef path.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If for some hierarchy configuration is not defined, then it inherits from the parent one; that is, in our case, if we do not define sling:configRef in ca\/b1\/jcr:content that it picks configuration values from ca, i.e., from a parent.<\/span><\/p>\n<h2><b>Results<\/b><\/h2>\n<p><b>For Ca =&gt;<\/b><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58716 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image14.png\" alt=\"\" width=\"934\" height=\"424\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image14.png 934w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image14-300x136.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image14-768x349.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image14-624x283.png 624w\" sizes=\"(max-width: 934px) 100vw, 934px\" \/><\/p>\n<p><b>For CA_b1 =&gt;<\/b><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58715 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image15.png\" alt=\"\" width=\"924\" height=\"377\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image15.png 924w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image15-300x122.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image15-768x313.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image15-624x255.png 624w\" sizes=\"(max-width: 924px) 100vw, 924px\" \/><\/p>\n<p><b>For CA_bK =&gt;<\/b><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58714 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image16.png\" alt=\"\" width=\"936\" height=\"393\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image16.png 936w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image16-300x126.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image16-768x322.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image16-624x262.png 624w\" sizes=\"(max-width: 936px) 100vw, 936px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">If we remove sling:configRef Property from \/content\/mysite\/ca\/b1\/jcr:content then it <\/span><span style=\"font-weight: 400;\">inherits<\/span><span style=\"font-weight: 400;\"> values from\u00a0<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\/content\/mysite\/ca\/jcr:content i.e parent.<\/span><\/pre>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58713 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image17.png\" alt=\"\" width=\"928\" height=\"389\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/image17.png 928w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image17-300x126.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image17-768x322.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/image17-624x262.png 624w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Use Case Imagine you have a special part on your website that shows different information based on where the website visitor is from. Let&#8217;s call it the &#8220;Location Info&#8221; part. This part is used in many places on the website, like different pages. Now, some places on the website have different needs \u2013 they want [&hellip;]<\/p>\n","protected":false},"author":1652,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":906},"categories":[5868],"tags":[5473,5472],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58732"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1652"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=58732"}],"version-history":[{"count":2,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58732\/revisions"}],"predecessor-version":[{"id":59113,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58732\/revisions\/59113"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=58732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=58732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=58732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}