Adobe Experience Manager | AEM/CQ | Apache Sling

Sync Crypto Keys across AEM 6.3 instances
In order to read data on one instance that was secured on another, you need to sync the Crypto keys across all of your instances. Prior to AEM 6.3, you would package up /etc/key and share it between your author and publish servers (See: How to Use Crypto support in Adobe CQ / AEM). However, in AEM 6.3 the Crypto keys were moved out of the JCR to make them more secure in case someone gains access to your CRXDE. Side note, ensure the public can't access CRXDE by going through the AEM 6.3 Security Checklist.

In order to sync the Crypto keys between servers in AEM 6.3:

  1. Find the bundle Id for com.adobe.granite.crypto.file, for example, 21. You can navigate to /system/console/bundles/com.adobe.granite.crypto.file to see the Id.
  2. Navigate to /crx-quickstart/launchpad/felix/bundle<Id>/data in the file system.
  3. Copy the two files: hmac and master from the source instance to the target instances.
  4. Restart the target com.adobe.granite.crypto bundle or the entire AEM instance.
There is a way to make AEM 6.3 read the Crypto keys from the JCR like you're currently familiar with, however, this is not recommended if you can avoid it. Start AEM 6.3 with the -Dcom.adobe.granite.crypto.file.disable=true flag. Note that this must happen on the first startup of the instance. The instance will not change behavior once AEM has been started with or without the flag.
Use custom Granite render conditions to determine if Touch UI components should display in AEM.
Granite render conditions can be used to determine whether a component should be rendered or not. From the Render Condition documentation, a "typical example would be to render a submit button based on whether the current user has a privilege to create or modify a resource." Render conditions can be used to help guide the author by dynamically customizing forms based on known information.

Download the sample project on GitHub at https://github.com/nateyolles/aem-granite-rendercondition-demo which includes various examples of utilizing the built-in render conditions as well as examples on how to create your own custom render conditions, how to pass in data to those render conditions and how to evaluate Expression Language with your custom render conditions.

Screenshot of an AEM admin form using Granite render conditions
There are many examples of render conditions throughout AEM and an easy way to start exploring is to query for the most basic render conditions from within CRXDE Lite using something like  /jcr:root//*[@sling:resourceType='granite/ui/components/foundation/renderconditions/simple']. You can find the standard render conditions such as  simpleandornot and  privilege under  /libs/granite/ui/components/foundation/renderconditions. There are a few custom render conditions under  /libs/cq/gui/components/projects/admin/renderconditions which you can explore, as well as  /libs/cq/gui/components/renderconditions/islocked/libs/wcm/msm/components/touch-ui/renderconditions/isblueprint and  /libs/wcm/msm/components/touch-ui/renderconditions/islivecopy. There is another great example of a custom render condition in the  ACS AEM Commons project which displays components based on the current path.

To utilize this server-side display logic, simply create a node under your Granite widget named granite:rendercondition, set the sling:resourceType to the render condition component such as granite/ui/components/foundation/renderconditions/simple and populate the required properties such as expression. For example, the following textfield will only render when the query string parameter biz equals baz.



Granite render conditions take advantage of JSP Expression Language or EL for short. As such, you have access to param, paramValues, header, headerValues, cookie, requestPathInfo, state and tenant. You also have access to a powerful, yet simple and straight-forward syntax to evaluate logic in Expression Language. Furthermore, Granite provides extra convenience with a few provided EL Functions. For example:



See the Granite UI Documentation on Expression Language for more information regarding available variables and functions. Note that EL expressions can be used outside of render conditions as well. For example, you'll find them granite/ui/components/foundation/hyperlink components to pass data forward, such as:



The simple render conditions are quick and readily available for most basic expressions. However, if you need custom logic, you can write your own render condition. A render condition is simply a JSP component. Within your custom logic you will get the granite:rendercondition resource, retrieve its relevant properties via the resource's Config and set a true or false  SimpleRenderCondition as a request attribute. To evaluate EL expressions, use the ExpressionHelper by way of the ExpressionResolver service, which is powered by the Apache Commons EL interpreter. The combination of a custom render condition and EL expressions is very powerful.



The custom render condition is used the same way the default render conditions are utilized, simply update the sling:resourceType to the path of your custom render condition component and populate your defined resource properties.



When you download the sample project at https://github.com/nateyolles/aem-granite-rendercondition-demo, you'll notice that the most straight-forward condition is the simple render condition and that you can combine conditions by nesting and, or and not conditions. This snippet from the demo project reveals a variety of ways to dynamically render Touch UI components including cookies, headers, query string parameters, selectors, suffixes, JCR privileges and custom render conditions.



You'll notice in the provided sample project that I created a custom Touch UI admin page to help demonstrate the various ways of using the Expression Language to interact with the URL. (If you're interested in how to do that, see Chris Millar's post on How to create an AEM 6.2 Admin Console for Touch UI.) Take note that render conditions work with any Granite widget, however, in specific scenarios, certain challenges exist when trying to use render conditions with component dialogs in your typical Touch UI editing of pages. Remember that an AJAX call is made to open the dialog and the EL expressions are evaluated on that AJAX request, not the request for the page which is in fact /editor.html. Therefore, the path, suffix, selectors and query string parameters are independent of what you see in your browser's address bar when using a normal component dialog in the editor.
Create custom HTML output for AEM clientlibs and Sightly to take advantage of HTML5 and enhance site performance.
AEM clientlibs are extremely powerful. They allow you to produce client-side JavaScript and CSS libraries while controlling minification, concatenation, and dependency management. However, out-of-the-box, they don't allow you to customize the HTML output. While optimizing your website for speed, you may want to use the defer, async, and/or onload attributes on your script elements. Likewise, while managing your cross-origin resource sharing (CORS) HTTP requests, you may want to utilize the crossorigin attribute on your script and/or link elements for JavaScript and CSS.


Using clientlibs in AEM with Sightly is demonstrated in the AEM documentation Using Client-Side Libraries, as well as Feike Visser's ( @heervisscher) Sightly intro part 5: FAQ.



When we follow the data-sly-use block's expression value in our AEM instance, we find three files that work together with the HtmlLibraryManager to provide the final clientlib output. clientlib.html contains named Sightly template blocks ( js, css, all), which in turn set the proper Sightly expression option for mode and call the named Sightly templates in graniteClientLib.html. graniteClientLib.html then sets the proper Sightly expression options and delegates the more complex logic to a Java-Use API POJO. ClientLibUseObject.java then utilizes the HtmlLibraryManager in order to write out the final HTML markup.

All files associated with Sightly clientlibs are viewable in your AEM instance under the /libs/granite/sightly/templates node. To make any alterations, we simply copy all three files out of /libs into /apps, update the files, and update our Sightly components to point to the new clientlib component (usually headlibs.html or similar partial in the page component).



In our case, we want to alter the HTML markup by adding additional attributes to the script and link elements. In order to do that, we first add additional Sightly expression options to all the Sightly templates. In this example, I'm using loading, onload, and crossorigin options.



Once the new Sightly expression options are set, the Java-Use POJO is updated to obtain those options from the provided bindings. AEM hands the responsibility of printing the final HTML markup to the HtmlLibraryManager's writeIncludes, writeCssInclude and writeJsInclude methods. However, since we want custom markup, we need to do that ourselves in the POJO.



I've written a demonstration AEM project as well provided the code which can easily be installed into a single folder for use in your project. There is also an AEM package available for easy install. View the AEM Clientlib Async project on GitHub.
Use com.adobe.granite.confmgr.ConfMgr in AEM to set multi-tenant, ACL protected, inheritance supplied configurations.
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 https://github.com/nateyolles/aem-slash-conf.

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.

/content/aviato
/content/piedpiper
/content/hooli
/content/hooli/hoolixyz

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 https://github.com/nateyolles/aem-slash-conf.

Thanks to Alex Klimetschek ( @alexkli) for sharing his knowledge of /conf of which much of this blog post is based on.
Custom validation in AEM Touch UI dialogs
Adobe Experience Manager's Touch UI provides a straightforward validation framework making it simple to create custom form element validators as well as to interface with them programmatically. This blog post details the inner workings of the AEM Touch UI Validation Library which provided unobtrusive validation and enhanced functionality to AEM's Granite UI foundation dialog components.

Custom Multifield validation in AEM's Touch UI dialog.

Registering custom validators is done by calling the jQuery based $.validator.register method. The register method takes a single JavaScript object literal argument. The parameter looks for four properties: selector, validate, show and clear, of which only selector is required.

The following example creates a custom validator for phone numbers in a Touch UI dialog. Note that show and clear methods are not necessary in this example as the validator would use the default AEM provided methods, however, they are included for reference.



The  selector property ties the validator to the form elements on the page. The property accepts any jQuery selector such as a class ( .my-class-name), type ( INPUT) or attribute ( INPUT[type="text"]) selectors.

The  validate property is the function that validates the form element's input. The function provides the form element as a jQuery object as the single available parameter. The field is treated as invalid if this function returns a string literal as the validation error message.

The  show and  clear properties are functions that update the UI when when the form element is determined to be invalid or valid respectively. Each function makes two parameters available, the form element as a jQuery object and the validation message.

The  selector property is obviously required, otherwise the validator can never be called. However, the  validateshow and  clear are optional. For example, if a form element is already being validated through an existing validator, you can update the UI behavior of the error message by registering a new validator with only  show and  clear functions. Order of registration is important; the last validator registered is the first validator used. View the  Granite UI Validation documentation for further information. AEM's default validators are located at  /libs/granite/ui/components/foundation/clientlibs/foundation/js/validation/validations.js

The most obvious reason for providing custom show and clear functions is to validate a custom dialog component. For example, in the AEM Touch UI Validation Library, the two functions are used in the multifield validator as the field used is an HTML textbox to validate and it's not in the same HTML structure as the other HTML textboxes that the default AEM validator has already registered.

The benefit of using the provided jQuery.validator plugin is that it becomes trivial to create custom validation with a consistent UI provided by AEM out-of-the-box. As you write your custom validators, note that the jQuery.validator plugin attempts to mimic the default HTML5 validation and more importantly, note that hidden fields are not validated.

AEM provides a simple jQuery API to interact with form elements:


Using the principles described in this blog post, I've created the AEM Touch UI Validation Library to provide enhanced validation to Granite dialog components such as the multifield, browserpath, radiogroup and autocomplete.