AEM /conf and ConfMgr

Adobe Experience Manager | AEM/CQ | Apache Sling

AEM /conf and ConfMgr

As of AEM 6.1 you may have noticed the new /conf node at the root level along with /content, /etc, /apps and /libs. Over time the /etc folder's responsibility has expanded and configurations have been moved in an effort to clean it up a little. Whereas prior to 6.1 you would have stored site configurations in /etc, it's now recommended that you store those configurations under /conf. Along with the new node structure Adobe has provided a valuable, yet simple, utility to help manage these new site configurations in com.adobe.granite.confmgr.ConfMgr and com.adobe.granite.confmgr.Conf.

Read the Adobe provided documentation for  Conf and ConfMgr.

I have created a demo project and hosted it on GitHub at

As an example, let's host a multi-tenant AEM instance with three projects and one subproject: Aviato, Pied Piper, Hooli and subproject Hooli XYZ.


Add a cq:conf property of type String at the root of every project page and point it to the site's corresponding configuration path. A global configuration will be used if a cq:conf property is not specified as is the case for Aviato in this example.

/content/piedpiper/jcr:content/@cq:conf = "/conf/tentants/piedpiper"
/content/hooli/jcr:content/@cq:conf = "/conf/tentants/hooli"
/content/hooli/hoolixyz/jcr:content/@cq:conf = "/conf/tentants/hooli/hoolixyz"

Conf respects relative paths as it pertains to the cq:conf property. Therefore, the following settings could also be used:

/content/hooli/jcr:content/@cq:conf = "/conf/tentants/hooli"
/content/hooli/hoolixyz/jcr:content/@cq:conf = "hoolixyz"

The tree structure of /conf should closely resemble /content. The configuration nodes should be of type cq:Page with the configuration properties on the jcr:content sub-nodes. All configurations start below the path specified in cq:conf with the addition of /settings.

/conf/global/settings/socialmedia/facebook/jcr:content/@enabled = false
/conf/tenants/piedpiper/settings/socialmedia/facebook/jcr:content/@enabled = true
/conf/tenants/hooli/settings/socialmedia/facebook/jcr:content/@enabled = true
/conf/tenants/hooli/hoolixyz/settings/socialmedia/facebook/jcr:content/@enabled = true

/conf/global is special as it provides an ultimate fallback in the Conf inheritance mechanism. It this example Aviato does not have its own config, so it would use the global configs. /conf/tenants is not dictated by AEM, but is a convention worth following to help prevent namespace collision in multi-tenant scenarios.

Configs can live under /conf, /apps and /libs with the same apps-then-libs type resolution that you are already familiar with. The resolution order can be set in the Felix console com.adobe.granite.confmgr.impl.ConfMgrImpl configuration: http://localhost:4502/system/console/configMgr/com.adobe.granite.confmgr.impl.ConfMgrImpl.

Use a Conf object to get a site configuration. The Conf object is usually obtained by adapted a Resource or Page using Apache Sling's adaptTo() method. Once you have the site's Conf object, you can get any number of predefined ValueMaps and properties. Notice that the ValueMaps cannot be modified – they are read-only. Properties are retrieved from the ValueMap in the familiar way of passing in either a default value or the class type.

The Conf object you retrieve is based on the path of the resource. So if have a Sling Model or WCMUsePojo and you adapt the current page, you will get a different Conf than if you adapt the current resource.

As you can see, the ConfMgr is a fairly lightweight and transparent helper. Everything is in the JCR, so configurations can be accessed through normal channels such as a Resource Resolver. However, there are three main benefits to using com.adobe.granite.confmgr.Conf.

The most obvious advantage is the built in inheritance management. For instance, the site for Hooli might have ten configurations. If the subproject Hooli XYZ overwrites only one of those configurations, it will use the other nine provided by Hooli. If the Conf object is looking for a config that doesn't exist in the subproject or project, it will look under /global. Conf inherits and overwrites at the node level, not the property level.

Conf handles null values for you. If the configuration, ValueMap or individual properties are null, you can continue without null checks and you won't get a Null Pointer Exception.

Conf respects ACLs and multi-tenant privacy. If you setup your ACLs correctly, a shared component between two tenants will still only be able to access the configurations of the current tenant. Conf does not allow relative paths that try to move up the tree and into another tenant (i.e. "../../differentSite/foo/bar").

ConMgr can be used as a service.

When used as a service, a Resource Resolver can be passed in which allows the use of Sling Service Accounts, thereby respecting ACLs on the configurations.

All inherited configurations can be obtained by using the Conf#getList() method, which returns a List of ValueMaps. Configurations can also be chosen explicitly by using a Resource Resolver to get the specific resource.

View a complete example at

Thanks to Alex Klimetschek ( @alexkli) for sharing his knowledge of /conf of which much of this blog post is based on.


Brodie Yazaki | March 28, 2016 at 05:49 PM | Reply

Very interesting, this is a much cleaner and safer way. I appreciate the fact that you can now really enforce ACLs and not have accidental "copy paste and get unexpected results that sit in prod for a few days" kind of incidents.

Nicolas | March 29, 2016 at 08:23 PM | Reply

Great post, really looking forward to see it in action :) Since configurations could be called massively in components it would be great to hear something about performance? Is there a caching layer implemented?

Nate Yolles | March 30, 2016 at 12:01 AM | Reply

Conf is essentially a Resource Resolver with some extra logic specific to its task and reading from a node in the JCR is a lightweight operation.

Andre | March 30, 2016 at 02:56 PM | Reply

Do you know a way, how content author would be able to maintain configurations? So that content authors can edit / nodes under the /conf structure in order to provide flexibilty?

Nate Yolles | March 30, 2016 at 09:44 PM | Reply

You want to create groups with permissions to edit the /conf nodes, one group per tenant to keep them separate. As far as I'm aware, if you need a UI outside of CRXDE Lite, you will have to create one.

Nono Junang | April 04, 2016 at 10:09 PM | Reply

Great extension and great post. As you mentioned the great benefit here is the inheritance of configuration and fallback. I would have expected Adobe to provide this functionality as part of or as an extension to the existing Sling Tenant API instead of creating a new api for that, because you can also save tenant configuration using the Sling Tenant API. I fear this will only get confusing over time.

Matthieu Tremblay | April 05, 2016 at 02:43 PM | Reply

Great write-up, thanks! Will be putting this to use in my future projects.

Kunal | April 11, 2016 at 10:14 AM | Reply

Great write-up.. Very interesting and github project provides a great point of reference. However could you please update the filter for ui.content from /content to /content/aviato, /content/hooli, /content/piedpiper and /content/dam/slashconfdemo as it deletes everything under /content and overrides with the new content.

Nate Yolles | April 14, 2016 at 05:21 PM | Reply

I used the default settings from the AEM archetype, but I can update the filter. Thank you!

tosheer kalra | April 12, 2016 at 05:58 AM | Reply

Nice feature with a great write-up. But why AEM hasn't given feature to update the config as page property in the OOTB page properties dialog or i am missing anything.

Nono Junang | May 17, 2016 at 10:58 AM | Reply

Hi Nate, Can you elaborate what the difference is between this approach and using the Cloud Service Configuration approach? Regards,

Alex | November 16, 2016 at 11:25 PM | Reply

Please note that you have to also allow anonymous for the conf nodes when running this on the publisher. I spent ages trying to figure out why the conf nodes weren't returning anything in the publisher before I figured out it was good old node permissions!

Vineet | February 28, 2017 at 02:22 PM | Reply

Its OK for new configurations. Is there any support for context aware configs for OOTB OSGi services?

Jonas | September 11, 2017 at 01:19 PM | Reply

This sounds like a good way to allow authors to administer global non-technical settings (e.g. contact information, name of ceo, etc.). How can the /conf nodes be replicated to the publisher instances?

Annacon | March 19, 2019 at 07:54 AM | Reply

Ð·Ð°Ð¹Ð¼Ñ Ð¾Ð½Ð»Ð°Ð¹Ð½ на ÐºÐ°Ñ Ñ Ñ Ñ Ð¿Ð¸Ñ Ð¾Ðº Ñ Ð°Ð¼Ñ Ðµ Ð½Ð¾Ð²Ñ Ðµ:

Austinnat | March 21, 2019 at 06:03 AM | Reply

Hydra Onion Shop - Ñ Ñ Ð¾ ÐºÑ Ñ Ð¿Ð½ÐµÐ¹Ñ Ð°Ñ Ñ Ð¾Ñ Ð³Ð¾Ð²Ð°Ñ Ð¿Ð»Ð¾Ñ Ð°Ð´ÐºÐ°, Ñ Ð°Ð±Ð¾Ñ Ð°Ñ Ñ Ð°Ñ Ð½Ð° Ñ ÐµÑ Ñ Ð¸Ñ Ð¾Ñ Ð¸Ð¸ СРР. Ð ÐµÐ¹Ñ Ð¸Ð½Ð³Ð¸, Ð¾Ñ Ð·Ñ Ð²Ñ , Ñ Ð°Ð·Ð²Ð¸Ñ Ñ Ð¹ Ñ Ð¾Ñ Ñ Ð¼. Ð Ñ Ðµ Ð´Ð»Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñ Ð½Ñ Ñ… и Ð°Ð½Ð¾Ð½Ð¸Ð½Ð¼Ñ Ñ… Ð¿Ð¾ÐºÑ Ð¿Ð¾Ðº. Ð Ð¾ÐºÑ Ð¿ÐºÐ° на Ð Ð¸Ð´Ñ Ðµ возможна Ñ ÐµÑ ÐµÐ· киви и Ð±Ð¸Ñ ÐºÐ¾Ð¸Ð½. Так же ÐµÑ Ñ Ñ Ð²Ð½Ñ Ñ Ñ ÐµÐ½Ð½Ð¸Ðµ обменники, но ÐºÑ Ñ Ñ Ñ Ð½Ð¸Ñ… Ð²Ñ ÐµÐ³Ð´Ð° Ð²Ñ Ñ Ð¾ÐºÐ¸Ð¹. <a href=>hydra center</a>

Vleorslicy | March 21, 2019 at 03:59 PM | Reply

Редавно Ð½Ð°Ñ ÐºÐ½Ñ Ð»Ñ Ñ Ð½Ð° Ð¾Ñ ÐµÐ½Ñ Ð¸Ð½Ñ ÐµÑ ÐµÑ Ð½Ñ Ñ Ð¼ÐµÑ Ð¾Ð´Ð¸ÐºÑ Ð·Ð°Ñ Ð°Ð±Ð¾Ñ ÐºÐ°. Ролго Ñ Ð¾Ð¼Ð½ÐµÐ²Ð°Ð»Ñ Ñ Ð¸ Ð´Ñ Ð¼Ð°Ð» Ñ Ñ Ð¾ ÐºÐ°ÐºÐ¾Ð¹Ñ Ð¾ Ð»Ð¾Ñ…Ð¾Ñ Ñ Ð¾Ð½, но Ð¾Ð¿Ñ Ð¾Ð±Ð¾Ð²Ð°Ð² Ð¼Ð¾Ð³Ñ Ñ ÐºÐ°Ð·Ð°Ñ Ñ Ñ Ñ Ð¾ Ð²Ñ Ðµ Ñ ÐµÐ°Ð»Ñ Ð½Ð¾ Ñ Ð°Ð±Ð¾Ñ Ð°ÐµÑ ! Ра Ñ Ð°Ð¹Ñ Ðµ Ð¿Ð¾Ð´Ñ Ð¾Ð±Ð½Ð¾ Ð¾Ð¿Ð¸Ñ Ð°Ð½Ð° Ð¼ÐµÑ Ð¾Ð´Ð¸ÐºÐ° Ð·Ð°Ñ Ð°Ð±Ð¾Ñ ÐºÐ° Ð¾Ñ 230 Ð´Ð¾Ð»Ð»Ð°Ñ Ð¾Ð² в Ð´ÐµÐ½Ñ ! Там ÐºÑ Ñ Ð° Ð¾Ñ Ð·Ñ Ð²Ð¾Ð² и ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ Ð°Ñ Ð¸ÐµÐ² Ð¾Ñ Ñ ÐµÐ°Ð»Ñ Ð½Ñ Ñ… Ð»Ñ Ð´ÐµÐ¹. Так Ñ Ñ Ð¾ ÐºÐ¾Ð¼Ñ Ð¸Ð½Ñ ÐµÑ ÐµÑ Ð½Ð¾ Ð¿Ñ Ð¾Ð±Ñ Ð¹Ñ Ðµ. Ð ÐµÑ Ð¾Ð´Ð¸ÐºÐ° Ð¾Ñ ÐµÐ½Ñ Ð¿Ñ Ð¾Ñ Ñ Ð°Ñ . <a href=></a>

Leave a Comment