Context-aware configuration in AEM
Use Case
Imagine you have a special part on your website that shows different information based on where the website visitor is from. Let’s call it the “Location Info” part. This part is used in many places on the website, like different pages. Now, some places on the website have different needs – 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.
However, a unique challenge arises – 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.
What is Context-aware configuration
When building a multi-national website with AEM, you may need to use different configurations for different country-specific pages.
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.
Steps for Implementation of Context-Aware Configuration
1. Context-aware configuration: To manage site-specific configurations, we can create a configuration class that defines configurations.
The @Configuration annotation is mandatory.
In the configuration class, we can define a set of properties that specify the default configuration values.
2. Using a model class to retrieve configurations
To use the Configuration class in our components, we need to create a model class that adapts to the configuration. Inside the Model class, we create a function that takes currentPage and ResourceResolver as Input.
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 org.apache.sling.caconfig.ConfigurationResolver – 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:-
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.
Internally, the ConfigurationResolver used the ConfigurationResourceResolver to get the configuration resources. It always uses the bucket name sling: configs.
Call that function by @PostConstruct annotation, where all variables get values from configuration.
3. Create Component
Inside the component, Model is used by data-sly-use and shows all values that it returns from Model on the page.
4. Create folders for every content resource inside /conf/mysite.
These folders are of jcr:primaryType = sling: folder.
For example:-
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.
5. Create a Configuration node.
Create a Configuration Node for every folder of jcr:primaryType = nt:unstructured.
And define values for every node according to the context.
6. 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.
For example:-
When we use a component on any page, it takes configuration according to sling:configRef path.
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.
Results
For Ca =>
For CA_b1 =>
For CA_bK =>
If we remove sling:configRef Property from /content/mysite/ca/b1/jcr:content then it inherits values from
/content/mysite/ca/jcr:content i.e parent.