AEM 5.6 - Quick Reference

Shortcuts

Query Parameters

  • ?wcmmode=( design | disabled | edit | preview )
  • ?debug=(layout | mdev | mdevc )
  • ?debugConsole=true
  • ?debugClientLibs=true

3rd Party Code Samples

CQ Component Icons (16x16)

Upload Film Strip (Orange) Reference Versions Title Lightbulb Text Entry Magnifying Glass Tag Flashlight Download Person Script Button Bulleted List Checkmark Dots Inverted Bulleted List Expand Pencil Stop Nested List Horizontal Lines Pagination Squares Tag Cloud Lightning Bolt Workflow Numbers Tree Paper Person and Number Dollar Sign Cycle Image Button Radio Button or Eye Image Password Horizontal Lines (Tight) Image and Text AT Sign Slideshow Sitemap Orange Grid Form Link Button Cloud Table Film Strip Flash Carousel Chart Credit Card Calendar Page Break Folder Word Bubble RSS Light Switch/Toggle Star Facebook Twitter Alternating Arrows Bars Twitter Bird RSS Blue Word Bubble (Blue) Word Bubble (Blue 2) Thumbs Up Profile Alert (Exclamation) Line Chart Audio

Conventions

Naming Conventions

Nodes

lowercase; dashes for spaces/special chars

  • Example: content-page, super-slideshow, video-player
  • Blacklist: config, install

Page Components are postfixed with the word "page"

  • Example: content-page, base-page, home-page

Properties

camelCase; no dashes, underscores, spaces

  • Example: pageTitle

Application Organization

/apps/site/components

Content components are the components that are placed ON a page and are not intended to represent the page template. All content components will have an (in)direct slign:resourceSuperType of the /apps/site/components/base component.

/apps/site/components/content /apps/site/components/title /apps/site/components/article /apps/site/components/accordian

Page components implement cq:Pages. All content components will have an (in)direct slign:resourceSuperType of the /apps/site/page/basepage component.

/apps/site/components/page /apps/site/components/page/base-page /apps/site/components/page/home-page /apps/site/components/page/section-page /apps/site/components/page/cotainer-page

sling:OsgiConfig nodes are added to the config folder to configure OSGi services.

/apps/site/config

global.jsp is included in every component JSP (content and page) and is used to include common objects into the pageContext.

/apps/site/global/global.jsp

cq:Template definitions are defined here. Futhur organization is at the discression of the developer.

/apps/site/templates

Any ExtJS widgets used for authoring inputs are maintained here.

/apps/site/widgets

CQ Workflow related assets are stored here.

  • scripts:: ecma scripts (needed for OR splits, etc.)
  • widgets: ExtJS widgets used for WF dialogs
  • dialogs: Custom dialogs used in Dialog Participant steps
/apps/site/workflow/scripts /apps/site/workflow/widgets /apps/site/workflow/dialogs

Client libs will contain the front-end assets managed by developers and not modifiable by Authors.

/etc/clientlibs/site/css /etc/clientlibs/site/images /etc/clientlibs/site/js

Multi-locale content organization

  • /<root>/<path>/gb_en/
  • /<root>/<path>/gb/<website>/en
  • /<root>/<path>/en

CRX2 Performance

Structure

  • Avoid 1000+ child nodes
  • Static content: higher tolerance for large # of child nodes; dynamic content: lower tolerance
  • Shard using <year>/<month>/<date>[/<hour>/<min>] or BTreeManager
  • When Traverse trees rather than Querying
  • Save in batches (~1024)

Query

Use QueryBuilder API; Generally avoid raw queries

  • Fast
    • jcr:primaryType match
    • Property comparison
    • Simple fulltext [jcr:contains(., 'keyword')]
    • Like on distinct values [jcr:like('@email', 'davidjgonzalez@%')]
  • Slow
    • jcr:contains with initial wildcard
    • Like on common values [jcr:like('@email', '%@gmail')]
    • Ranges
    • Path constraints

Component Organization

Adobe AEM Component Properties

/apps/.../sample /apps/.../sample/analytics /apps/.../sample/clientlibs /apps/.../sample/clientlibs/css /apps/.../sample/clientlibs/js /apps/.../sample/clientlibs/css.txt /apps/.../sample/clientlibs/js.txt /apps/.../sample/cq:editConfig /apps/.../sample/cq:htmlTag /apps/.../sample/cq:template /apps/.../sample/dialog /apps/.../sample/design_dialog /apps/.../sample/icon.png /apps/.../sample/sample.jsp /apps/.../sample/post.POST.jsp /apps/.../sample/views/x.jsp /apps/.../sample/partials/y.jsp

OSGi Services Checklist

OSGi Services are usually singletons.

  • Follows package organization
    • Put implemenations under .impl packages
  • Has logger named 'log'
  • Avoid mutable service state outside of conrtrolled life-cycle events (activate, deactivate, bind, unbind)
    • Else, use synchronized/atomic access to mutable state
  • @Component
    • label, description, metatype
    • label = "<Project Name> - <Service Name>"
      • Example: "Acme Inc. - FooBar
    • Use default of: immediate = false (unless runs autonomously)
  • Consistent @Property declarations
    • Default value: DEFAULT_FOO
    • Property field: foo
    • Property name: PROP_FOO
  • Use Sling PropertiesUtil to read @Properties
  • ResourceResolver/JCR Sessions are NOT thread safe
    • Do not persist in Service state
  • Avoid leaking presentation into Services
    • Exceptions include JSON/XML endpoints
  • Unit tested

CQ Component Checklist

  • Choose a presentation approach and stick with it!!!
    Avoid mixing Scriptlets and EL/JSTL.
  • Follows component organization
  • Follows naming conventions
  • i18n support for non-authorable text
  • XSS protect all ouput
  • Has jcr:title, jcr:description
  • Has cq:componentGroup
    • ".hidden" for fixed components
  • Includes app's global.jsp
  • Handles "unconfigured views" (cq-*-placeholders)
  • Implements applicable Drop Targets
  • Business logic moved to OSGi Services
  • Analytics node defined
    • cq:trackevents, cq:trackvars
  • Move inline CSS to clientlibs
    • Scope component-specific CSS with component-specific selector
  • Move inline JS to clientlibs;
    • Component instance params exposed via data-* attributes

OSGi Service Rankings

  1. Higher service ranking wins
    • Constants.SERVICE_RANKING
  2. In a tie, the lowest Service ID wins (registered first)
    • Constants.SERVICE_ID

ACLs/Permissions

  • Permissions resolve using bottom-up approach; First applicable ancestory rep:policy is used.
  • Per-node collision precedence based on order in ACL list AND order of membership on Principal; Be careful.
  • User permissions override Group permssions
  • rep:policy nodes NOT replicated

Reading and Writing to Nodes

Use Resources/ ValueMaps for READING data – Use Nodes for WRITING data

Getting a Resource and/or ValueMap

Resource myResource = resourceResolver.resolve("/path/to/my/pet"); ValueMap myProperties = myResource.adaptTo(ValueMap.class); // Default value of "Ira" if no property exists String pet = myProperties.get("name", "Ira"); // No default value, but converts to String[] String[] petSounds = myProperties.get("sounds", String[].class);

If you know the full path to a resource, use .getResource(..) instead of .resolve(..)

Resource myResource = resourceResolver.getResource("/path/to/my/pet");

You can get related nodes by...

Resource parent = myResource.getParent(); Resource descendant = myResource.getChild("great/grand/child"); Iterator children = myResource.listChildren();

On CQ 5.6+..

ModifiableValueMap props = myResource.adaptTo(ModifiableValueMap.class); props.put("color", "golden"); props.remove("sound"); props.save();

Otherwise, write to a node, use JcrUtil or JCR apis.

Node node = myResource.adaptTo(Node.class); JcrUtil.setProperty(node, "myProperty", "some value!"); node.getSession().save();

In some contexts you only have a Node; turn it into a Resource or ValueMap to read from it.

Resource myResource = resourceResolver.getResource(node.getPath()) ; ValueMap myProperties = myResource.adaptTo(ValueMap.class);

Default Content

Components

Create a cq:template node under the cq:Component and populate with default properties or default resource tree

/apps/.../demo[cq:Component] /apps/.../demo/cq:template[nt:unstructured] /apps/.../demo/cq:template@cat = "meow" /apps/.../demo/cq:template@sling:resourceType = ".../demo"

Templates

Create a jcr:content node under the cq:Template and populate with default properties or default resource tree

Data Access/DTO

Use Resources/ValueMaps for READING data.

Use Nodes for WRITING data.

Augmenting Resource ValueMaps

ValueMap props1 = resource.adaptTo(ValueMap.class); Map map = props1.getMap(); map.put("customKey", "custom data"); ValueMap props2 = new ValueMapDecorator(map);

Custom ValueMaps

Map map = new HashMap(); map.put("customKey", "custom data"); ValueMap props = new ValueMapDecorator(map);

Resource inclusion

[..] indicates optional

cq:include

Path accepts

  1. '.' for current resource
  2. relative or absolute resource path
  3. optional selectors applied to 1 or 2

<cq:include path="[/]some/resource[.s1.s2]" resourceType="some/component">

sling:include

  • If resourceType not set, sling:resourceType of target is used
<sling:include path="[/]some/resource" [resourceType="some/component"]> [addSelectors="s1.s2"] [replaceSelectors="s3.s4"] [replaceSuffix="foo/bar"]

Java Snippets

Inheritance ValueMaps

Use with hierarchy nodes such as CQ Pages, whose content is stored under jcr:content.

  1. First the property is searched inside the current resource
  2. If not found, looks for at relative path under closest ancestors jcr:content node
  3. Repeats until property is found or jcr root is reached
Resource resource = currentPage.getContentResource(); InheritanceValueMap valueMap = new HierarchyNodeInheritanceValueMap(resource); String val = valueMap.getInherited("foo", String.class);

Get a ResourceResolver from a JCR Session

In AEM6+ it is better to use `loginService()` using custom Service Users instead of `loginAdministrative()`. @Reference ResourceResolverFactory rrf; ... Map<String, Object> authInfo = new HashMap<String, Object>(); authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, jcrSession); ResourceResolver rr = rrf.getResourceResolver(authInfo);

Getting an OSGi Service

From a POJO? Don't! Pass in the service.

From a JSP

<% sling.getService(SampleService.class); sling.getServices(SampleService.class, "(uid=foo)"); %>

From an OSGi Service

@Reference(target = "(myprop=foo)") SampleService sampleService;

Getting a ResourceResolver

Whenever possible, use the ResourceResolver exposed via Sling and the SlingHttpServletRequest obj.

In code not associated with a HTTP Request (ex. workflow, events) you may retrieve a ResourceResolver for a specific user.

NOTE: Avoid using the admin ResourceResolver/Session whenever possible; Instead use a service account whose access is tailored to the use-case.

@Reference SlingRepository slingRepository; ... Session adminSession = repo.loginAdministrative(null); Session session = adminSession.impersonate( new SimpleCredentials("userIdToImpersonate", new char[0])); adminSession.logout(); ... // When you're done, close the impersonate session session.logout();

Creating CRX Login Tokens

Create a login token for a specific user.

@Reference private SlingRepository slingRepository; ... // Typically in an @Activate method this.repositoryId = slingRepository.getDescriptor(REPO_DESC_CLUSTER_ID); if(StringUtils.isBlank(this.repositoryId)) { this.repositoryId = slingRepository.getDescriptor(REPO_DESC_ID); } if(StringUtils.isBlank(this.repositoryId)) { this.repositoryId = slingSettings.getSlingId(); } if(StringUtils.isBlank(this.repositoryId)) { this.repositoryId = UUID.randomUUID().toString(); log.error("Unable to get Repository ID; falling back to a random UUID."); } // Create the login-token and set to the response TokenUtil.createCredentials(request, response, repository, userId, true);

Workflow

Start Workflow programmatically

@Reference WorkflowService wfService; ... WorkflowSession wfSession = wfService.getWorkflowSession(jcrSession); WorkflowModel model = wfSession.getModel("/etc/workflow/models/x/jcr:content/model"); WorkflowData data = wfSession.newWorkflowData("JCR_PATH", payloadPath); Workflow workflow = wfSession.startWorkflow(model, data);

CQ Workflow history

List<HistoryItem> history = workflowSession.getHistory(workItem.getWorkflow());

Get user properties

First method respects ClientContext user simulation

UserProperties props = slingRequest.adaptTo(UserProperties.class);

or

@Reference private UserPropertiesService ups; ... UserPropertiesManager upm = ups.createUserPropertiesManager(resolver); Authorizable authorizable = resolver.adaptTo(Authorizable.class); UserProperties properties = upm.getUserProperties(authorizable, "profile");

or

UserPropertiesManager upm = resolver.adaptTo(UserPropertiesManager.class); Authorizable authorizable = resolver.adaptTo(Authorizable.class); UserProperties props = upm.getUserProperties(authorizable, "profile");

Sling Servlet definition

Sling Servlet annotations

Configurations methods, resourceTypes, selectors, extensions are IGNORED if paths is set.

Methods defaults to GET if not specified.

@SlingServlet( label = "Samples - Sling Servlet", description = "...", paths = {"/services/all-sample"}, methods = {"GET", "POST"}, resourceTypes = {}, selectors = {"print.a4"}, extensions = {"html", "htm"} )

Safe Methods Servlet (GET, HEAD)

public class SampleServlet extends SlingSafeMethodsServlet implements OptingServlet { @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { ... } }

All Methods Servlet (GET, HEAD, POST, PUT, DELETE)

public class SampleServlet extends SlingAllMethodsServlet implements OptingServlet { @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { ... } }

Sling Filter definition

  • order: The smaller the number, the earlier in the Filter chain (can go negative); Defaults to Integer.MAX_VALUE which push it at the end of the chain
  • scope: SlingFilterScope.REQUEST, INCLUDE, FORWARD, ERROR, COMPONENT (REQUEST, INCLUDE, COMPONENT)
@SlingFilter( label = "Samples - Sling Filter", description = "...", metatype = true, generateComponent = true, generateService = true, order = 0, scope = SlingFilterScope.REQUEST) public class SampleSlingFilter implements javax.servlet.Filter { ... }

JavaScript Snippets

Add action button to sidekick

Add the following to a clientlib with categories = [cq.widgets]

CQ.Ext.namespace("app", "app.sidekick", "app.sidekick.actions"); app.sidekick.actions.MyButton = { "context": CQ.wcm.Sidekick.PAGE, /* CQ.wcm.Sidekick.PAGE CQ.wcm.Sidekick.COMPONENTS CQ.wcm.Sidekick.WORKFLOW CQ.wcm.Sidekick.VERSIONING CQ.wcm.Sidekick.INFO */ "text": "My Button", "handler": function() { alert("Do something!"); } }; // Add to bottom of list CQ.wcm.Sidekick.DEFAULT_ACTIONS.push(app.sidekick.actions.MyButton); // Insert into list CQ.wcm.Sidekick.DEFAULT_ACTIONS.splice(2, app.sidekick.actions.MyButton);

WCM APIs

To be used on CQ Author

var [CQ.WCM.Page] page = CQ.WCM.getPage('/content/path/to/page'); CQ.WCM.getContentUrl(); CQ.WCM.isEditMode(); CQ.WCM.isDesignMode(); CQ.WCM.isPreviewMode(); CQ.WCM.setMode( CQ.WCM.MODE_EDIT | CQ.WCM.MODE_DESIGN | CQ.WCM.MODE_PREVIEW );

i18n

var userName = "David"; CQ.I18n.getMessage("Hello from {0}", userName);

URI APIs

Current URI

CQ.shared.HTTP.getPath() CQ.shared.HTTP.getSelectors() CQ.shared.HTTP.getSuffix() CQ.shared.HTTP.getExtension()

HTTP/AJAX APIs

For synchronous HTTP Requests: Do not pass in the Callback function

GET Request

var suppressForbiddenCheck = true; CQ.shared.HTTP.get('/content/geometrixx/en.json', function(options, success, response) { console.log(options); // Request options console.log(success); // true/false console.log(response); // Response obj if(success) { // eval turns JSON response to JS Obj var myPage = CQ.shared.HTTP.eval(response); console.log(myPage['jcr:primaryType']) } }, this, suppressForbiddenCheck);

POST Request

var suppressErrorMsg = false; var suppressForbiddenCheck = true; var data = { city: 'Charlestown', state: 'MA', } CQ.shared.HTTP.post('/home/users/a/admin/profile/me', function(options, success, xhr, response) { console.log(options); // Request options console.log(success); // true/false console.log(xhr); // w3c xhr console.log(response); // Response if(success) { console.log('Profile Location Updated!'); } }, data, this, supressErrorMsg, supressForbiddenCheck);

XSS Protection

var unsafe = '<script>alert("foo")</script>'; CQ.shared.XSS.getXSSValue(unsafe);

ClientContext

Parameter format: storeName/propertyName

ClientContext.get('profile/authorizableId');

Set and retrieve attributes. (Set auto-persists to ClientContext Store)

ClientContext.set('profile/initials', 'DG'); ClientContext.get('profile/initials'); //=> 'DG'

Persist Store data to the defined persistance layer (usually Cookie)

ClientContext.persist('profile');

Reset ClientContext store to its 'init' state

ClientContext.reset();

Remove all properties/values from ClientContext Store

ClientContext.clear();

ClientContext Stores can be interacted with directly. This is helpful for custom Stores that implement custom APIs.

CQ_Analytics.ProfileDataMgr.getData() //=> {authorizableId : "anonymous", etc : '...' } CQ_Analytics.ProfileDataMgr.getProperty('authorizableId') // Persists automatically CQ_Analytics.ProfileDataMgr.setProperty('foo', 'bar') CQ_Analytics.ProfileDataMgr.getProperty('foo') //=> 'bar'

Wait for a ClientContext Store to load before using it.

CQ_Analytics.ClientContextUtils.onStoreInitialized("profile",function(store) { console.log(ClientContext.get('profile/authorizableId')); }, true);

Code Templates

OSGi Service Declaration

@Component( label = "Service name", description = "Service description", metatype = true, immediate = false) @Properties({ @Property( label = "My Label" name = "property-name", value = "my value", propertyPrivate = true ) }) @Service public class SampleServiceImpl implements SampleService { private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * OSGi Properties * */ private static final String DEFAULT_SAMPLE = "hello!"; private String mySample = DEFAULT_SAMPLE; @Property(label = "Prop name", description = "Prop description", value = DEFAULT_SAMPLE) public static final String PROP_SAMPLE = "sample"; ... @Activate protected void activate(final Map<String, String> config) { mySample = PropertiesUtil.toString(config.get(PROP_SAMPLE), DEFAULT_SAMPLE); } @Deactivate protected void deactivate(final Map<String, String> config) { } }

CQ Component JSP

<%@include file="/apps/../global/global.jsp"%><% %><%@page session="false" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="com.site.components.SampleComponent"%><% /** * BEGIN COMPONENT INITIALIZATION; * MAJORITY OF LOGIC SHOULD BE ABSTRACTED INTO THE OSGi SERVICE LAYER **/ final SampleComponent c = sling.getService(SampleComponent.class); final List<String> list = c.doSomething(slingRequest); /** BEGIN MARKUP; MINIMAL LOGIC AFTER THIS POINT **/ %> <%-- Use cq:text to display values from the resource as it supports Diffing --%> <cq:text property="jcr:title" tagName="h2"/> <%-- Any hardcoded values, including default values should be passed through i18n.get(..) or i18n.var(..) for future localization compatability --%> <h3><%= i18n.get("My List") %></h3> <ul class="my-list"> <% for(final String item : list) { %> <li><%= item %></li> <%= <% } %> </ul>

CQ Component JavaScript

Supporting JavaScript should be unobtrusive (not in the Component JSP), but rather maintained and served from a clientlib.

Component instance specific data or parameters can be written to the component as data-* attributes, and then read by the supporting JavaScript.

$(function() { $('.js-myapp-components-content-sample .my-link').on('click', function() { var $this = $(this); var componentName = $(this).data('component-name'); var alertMsg = $(this).data('alert-message'); alert(componentName + ': ' + alertMsg); }); });

.content.xml

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured"/>

CQ Component Dialog

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="cq:Dialog" activeTab="0" title="Component Title" xtype="tabpanel"> <items jcr:primaryType="cq:WidgetCollection"> <tab1 jcr:primaryType="cq:Widget" title="Tab 1" xtype="panel"> <items jcr:primaryType="cq:WidgetCollection"> <checkbox jcr:primaryType="cq:Widget" fieldLabel="Checkbox" fieldDescription="" defaultValue="false" inputValue="true" name="./checkbox" type="checkbox" xtype="selection"/> <cqinclude jcr:primaryType="cq:Widget" path="/path/to/other/dialog/inputs.infinity.json" xtype="cqinclude"/> <datetime jcr:primaryType="cq:Widget" fieldLabel="Date Time" fieldDescription="" name="./dateTime" allowBlank="{Boolean}true" xtype="datetime"/> <dialogfieldset jcr:primaryType="cq:Widget" collapsed="{Boolean}true" collapsible="{Boolean}true" title="Fieldset Title" xtype="dialogfieldset> <items jcr:primaryType="cq:WidgetCollection"> </items> </dialogfieldset> <displayfield jcr:primaryType="cq:Widget" ignoreData="{Boolean}true" hideLabel="{Boolean}true" hidden="{Boolean}false" value="Escaped HTML or plain-text to display" xtype="displayfield"/> <dropdown jcr:primaryType="cq:Widget" fieldLabel="Dropdown" fieldDescription="" defaultValue="" name="./dropdown" type="select" xtype="selection"> <options jcr:primaryType="cq:WidgetCollection"> <children jcr:primaryType="nt:unstructured" text="Option 1" value="option1"/> <descendants jcr:primaryType="nt:unstructured" text="Option 2" value="option2"/> </options> </dropdown> <html5smartfile jcr:primaryType="cq:Widget" autoUploadDelay="1" ddGroups="[media]" fieldLabel="HTML 5 Smart File" fieldDescription="" fileNameParameter="./fileName" fileReferenceParameter="./fileReference" name="./file" xtype="html5smartfile"/> <inlinetextfield jcr:primaryType="cq:Widget" fieldLabel="Inline Text Field" fieldDescription="" name="./inlineTextField" xtype="inlinetextfield"/> <ownerdraw jcr:primaryType="cq:Widget" fieldLabel="Owner Draw" fieldDescription="" html="HTML fragment to use as the owner draw's body content" name="./ownerDraw" url="The URL to retrieve the HTML code from. Replaces HTML defined in html." xtype="ownerdraw"/> <paragraphreference jcr:primaryType="cq:Widget" fieldLabel="Paragraph Reference" fieldDescription="" name="./paragraphReference" xtype="paragraphreference"/> <multifield jcr:primaryType="cq:Widget" fieldLabel="Multifield" fieldDescription="Click the '+' to add a new page" name="./multifield" xtype="multifield"> <fieldConfig jcr:primaryType="cq:Widget" width="155" xtype="pathfield"/> </multifield> <pathfield jcr:primaryType="cq:Widget" fieldLabel="Pathfield" fieldDescription="Drop files or pages from the Content Finder" name="./pathfield" rootPath="/content" suffix=".html" showTitlesInTree="{Boolean}true" typeAhead="{Boolean}true" xtype="pathfield"/> <radiobuttons jcr:primaryType="cq:Widget" fieldLabel="Radio button" fieldDescription="Field Description" name="./radioButton defaultValue="option1" type="radio" xtype="selection"> <options jcr:primaryType="cq:WidgetCollection"> <option1 jcr:primaryType="nt:unstructured" text="Option 1" value="option1"/> <option2 jcr:primaryType="nt:unstructured" text="Option 2" value="option2"/> </options> </radiobuttons> <resType jcr:primaryType="cq:Widget" ignoreData="{Boolean}true" name="./sling:resourceType" value="some/resource/type" xtype="hidden"/> <richtext jcr:primaryType="cq:Widget" fieldLabel="Rich Text" fieldDescription="" defaultValue="" hideLabel="{Boolean}true" name="./richText" xtype="richtext"> <rtePlugins jcr:primaryType="nt:unstructured"> <table jcr:primaryType="nt:unstructured" features="*"/> </rtePlugins> </richtext> <searchfield jcr:primaryType="cq:Widget" fieldDescription="" fieldLabel="Search Field" name="./searchField" url="The URL where the search request is sent to (defaults to "/content.search.json")" xtype="searchfield"/> <sizefield jcr:primaryType="cq:Widget" fieldLabel="Sizefield" fieldDescription="" heightParameter="./height" widthParameter="./width" heightSuffix="px" widthSuffix="px" xtype="sizefield"/> <textarea jcr:primaryType="cq:Widget" fieldLabel="Textarea" name="./textarea" grow="{Boolean}true" xtype="textarea"/> <textfield jcr:primaryType="cq:Widget" fieldLabel="Textfield" name="./textfield" xtype="textfield"/> </items> </tab1> <tab2 jcr:primaryType="cq:Widget" title="Image" allowUpload="{Boolean}false" cropParameter="./image/imageCrop" ddGroups="[media]" fileNameParameter="./image/fileName" fileReferenceParameter="./image/fileReference" mapParameter="./image/imageMap" name="./image/file" requestSuffix="/image.img.png" rotateParameter="./image/imageRotate" sizeLimit="100" xtype="html5smartimage"/> </items> </jcr:root>

http vhost-config.conf

<VirtualHost *:80> ServerAdmin webmaster@localhost ServerName mysite.com DocumentRoot /opt/aem/cache <Directory /opt/aem/cache> Options FollowSymLinks AllowOverride None </Directory> <IfModule disp_apache2.c> SetHandler dispatcher-handler </IfModule> # BEGIN REWRITE RULES # Rewrite rules will pre-pend the AEM path prefix to requests to content pages RewriteEngine On # Prevent other page content trees from being served from this domain (dam and campaigns are OK) RewriteCond %{REQUEST_URI} ^/content RewriteCond %{REQUEST_URI} !^/content/campaigns RewriteCond %{REQUEST_URI} !^/content/dam RewriteRule !^/content/mysite/en - [R=404,L,NC] # Home page re-writing # mysite.com/ or mysite.com/home > Home page RewriteCond %{REQUEST_URI} ^/$ RewriteCond %{REQUEST_URI} ^home$ RewriteRule ^/(.*)$ /content/mysite/en.html [PT,L] # Ignore requests to "known" AEM root paths, and prefix all others with the proper AEM prefix RewriteCond %{REQUEST_URI} !^/apps RewriteCond %{REQUEST_URI} !^/content RewriteCond %{REQUEST_URI} !^/etc RewriteCond %{REQUEST_URI} !^/home RewriteCond %{REQUEST_URI} !^/libs RewriteCond %{REQUEST_URI} !^/tmp RewriteCond %{REQUEST_URI} !^/var RewriteRule ^/(.*)$ /content/mysite/en/$1 [PT,L] LogLevel warn CustomLog ${APACHE_LOG_DIR}/access-mysite.com.log combined ErrorLog ${APACHE_LOG_DIR}/error-mysite.com.log # Shamlessly stolen from: http://www.cognifide.com/blogs/cq/multidomain-cq-mappings-and-apache-configuration/