Article summary

Summary

This development article discusses how to create Experience Manager 6.3 components. Included in this article are the following topics: 

  • Create an Experience Manager project by using Lazybones.
  • Setup the project using the Eclipse plug-in.
  • How to create a simple component.
  • How to create an HTL component that uses Sling Models. 
  • How to create Proxy components based on Experience Manager Core components.  

A special thank you to Ranta and Navin Kaushal, top AEM community members, for testing this article to ensure it works.

Digital Marketing Solution(s) Adobe Experience Manager 6.3
Audience Developer
Required Skills Java, HTML, JavaScript
Version 6.3

Prerequisites

To follow along with this article, you need the JDK version 1.8 and Eclipse NEON (Eclipse Java EE IDE for Web Developers) that you can download from here: https://www.eclipse.org/downloads/. Then download the installer.

Introduction

When working with Adobe Experience Manager projects, you often need to develop custom components to address your business requirements. This article discusses how to on board new developers to Experience Manager and build custom components. This article starts by creating a properly structured Experience Manager project that follows best practices. That is, it discusses specific tooling for both Java developers and front-end developers, as well as how to edit the rendered markup with HTL and Sling models.

In addition, this article covers working with Experience Manager Core Components. For information, see Core Components.

Custom components displayed in the Experience Manager Side Rail

Setup Lazybones

Lazybones is installed using a two-step process. First, install sdkman, a Sofware Development Kit management system. Instructions for installing sdkman can be found at http://sdkman.io/install.html.

In a Terminal window, run these two commands:

  • curl -s "https://get.sdkman.io" | bash
  • source ~/.sdkman/bin/sdkman-init.sh

Once sdkman is installed, you can use it to install lazybones with the following command:

sdk install lazybones

And then open a new Terminal window.

Note:

Windows users can find a PowerShell version of sdkman at https://github.com/flofreud/posh-gvm. It might also be easier to download the Lazybones distribution, unzip it, and add it to your path. See https://github.com/pledbrook/lazybones#running-it.

Setup Eclipse to communicate with Experience Manager

Setup Eclipse Neon to interact with Experience Manager. 

Install the Eclipse Experience Manager plugin

Install the Experience Manager Eclipse Plugin by performing these tasks: 

1. With Eclipse open, select Install New Software from Help menu.

2. Click Add button.

3. In the Name field, enter AEM Developer Tools.

4. In the Location field, enter https://eclipse.adobe.com/aem/dev-tools/.

5. Click OK.

6. Check both the AEM and Sling checkboxes (or just push the Select All button).

7. Click the Next button.

8. On the Install Details dialog, click the Next button.

9. Accept the license terms and click the Finish button.

10. Restart Eclipse.
 

Configure Eclipse to communicate with Experience Manager

Perform these tasks: 

1. In Eclipse, click on the Servers view (Window, Show View, Servers).

Server view in Eclipse

2. Click the link to create a new server.

3. In the New Server dialog, make sure that Adobe Experience Manager is selected and click the Finish button.
 

Adobe Experience Manager in Eclipse

4. Once the Server is created, click on it.

5. Change the port number to 4502.

6. In the Install panel, select Install bundles via bundle upload. You will see the view as shown in this illustration. 

Setting up the server in Eclipse

7. Click File, Save.

8. Close the Adobe Experience Manager at Localhost tab.

9. Right click on the entry in the Servers view and select Start.
 

The Server view

10. Verify that the entry in the Servers view shows as Started.
 

Experience Manager Server is started

Create a Lazybones project

You can use Lazybones to create an Experience Manager project. Lazybones is a project creation tool that uses templates to create projects. Once created, you can import the project into Eclipse. 

To create an Experience Manager project by using Lazybones, perform these tasks:

1. Open another Terminal (on Windows, you can use a tool like Git Bash).

2. Navigate to the user root folder.

3. Enter the following command:

    lazybones create aem-multimodule-project my-project

4. Answer the questions with the default values  (enter return for all questions). 

5. Once the project is built successfully, you will see the following message. 

A successful message that the Lazybones project was created

Note:

For more information about creating the Lazybone project (including all the input values) for Experience Manager, see Create AEM Project Structure using Lazybones.

Import the Lazybones project into Eclipse

Import the project into Eclipse by performing the following tasks:  

1. Start Eclipse.

2. Open the File menu and select Import. In the Import type, select Existing Maven Projects (inside the Maven folder).

Maven option within Eclipse

3. Click the Next button. 

4. Click the Browse button and select the my-project folder (if you chose a different folder name when generating the project, select it instead).

The Lazybones project being imported into Eclipse

5. Click Finish

Once you successfully import the project into Eclipse, you can view the project, as shown in this illustration. 

Lazybones generated files

These projects serve different purposes:

  • example-project.ui.apps - contains configuration, server-side scripts, client-side scripts, and styling code (CSS). 
  • example-project.core - contains Java code which is deployed to AEM as an OSGi bundle.
  • my-project - acts as the container for the two other projects. 

 

Note:

Under the Sling source path, you may need to delete two error handler JSPs from Eclipse. 

Create basic components

You can create an Experience Manager component for use in Experience Manager projects. In this section, two components are copied into the Eclipse project. 

Download

Import the components into the Eclipse project

Download the package that is available and unzip it. The following illustration shows the extracted file system. 

 

Contents of the ZIP file

The multiline and simple folder contains the components that are imported into Experience Manager. The parent folder for these components is named snippets. Copy the snippets folder and paste into the Eclipse project at the following location: 

 

Copy the snippets folder into the Eclipse project

Note:

Make sure that you copy the snippets folder and paste under the content folder, as shown in the previous illustration. 

If you are presented with a dialog, select the following option: Copy files and folders and click Ok. 

When you successfully copy the files you have two new components in your Eclipse project. The following code represents the simple HTL component.

Simple component

<h3>Summit 2017 L3845 Text Component, please add some text</h3>
<p class="${text.cssClass}" data-emptytext="Text">${properties.text}</p>

Notice the node under the simple component named cq:dialog. This represents the components dialog. The following code represents the dialog. 

<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"
    jcr:title="Title"
    sling:resourceType="cq/gui/components/authoring/dialog"
    helpPath="https://www.adobe.com/go/aem6_2_docs_component_en#Title - HTL">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/foundation/container">
        <layout
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
            margin="{Boolean}false"/>
        <items jcr:primaryType="nt:unstructured">
            <column
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/foundation/container">
                <items jcr:primaryType="nt:unstructured">
                    <text
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/foundation/form/textfield"
                        fieldDescription="Please enter your summit text here."
                        fieldLabel="Text"
                        name="./text"/>
                </items>
            </column>
        </items>
    </content>
</jcr:root>

This component dialog is a Touch UI dialog. Notice text element defines the resource type:

sling:resourceType="granite/ui/components/foundation/form/textfield"

This element is a text field whose name is ./text. Notice the component logic. It prints out the value that an author enters into the dialog. 

${properties.text}

Multiline component

The multiline component displays a repeating data set that an author enters into the component dialog. This component uses a Java backend that represents a sling model that stores the data into an array. The following code represents the front end of the HTML component (the multiline.html). 

<sly data-sly-use.model="com.adobe.summit2017.l3845.models.MultilineModel" />

<h3>Summit 2017 L3845 Multiline Component, please add some lines</h3>
<p class="${text.cssClass}" data-emptytext="Text">${properties.text}</p>
<ul data-sly-list.line="${properties.lines}">
  <li>${line}</li>
</ul>
<p>Number of Lines: ${model.numLines}</p>

In this example, notice this line of code: 

<sly data-sly-use.model="com.adobe.summit2017.l3845.models.MultilineModel" />

This informs the HTL component to use a Java backend class that uses Sling Models. The fully quaified path of the Java class is specified: com.adobe.summit2017.l3845.models.MultilineModel.

This code:

 

<ul data-sly-list.line="${properties.lines}">
  <li>${line}</li>
</ul>

writes out the value of the lines data member in the MultilineModel class. The code is not invoking the model-class, just using the properties object. 

This line of code: 

<p>Number of Lines: ${model.numLines}</p>

invokes the getNumLines method in the MultilineModel class.

The way the getNumLines is invoked is using a Sling Model. This is how you can invoke a method in a Java class from a HTL front end component using a Sling Model. The getNumLines returns a hard-coded value in this article (see the Java code later in this section). 

The following code represents the MultilineModel class. 

package com.adobe.summit2017.l3845.models;

import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Model(adaptables=Resource.class)
public class MultilineModel {
	
	
	/** Default log. */
	protected final Logger log = LoggerFactory.getLogger(this.getClass());

	@ValueMapValue @Default(values={})
	private String[] lines;
	
	public int getNumLines() { 
		int size = 1;  //specify a return value that shows up in the HTL component
		log.info("*** HERE IN getNum Method ***") ; 
		return size ; 
		
	}
}

A Sling Model is implemented in an OSGi bundle. A Java class located in the OSGi bundle is annotated with @Model and the adaptable class (for example, @Model(adaptables = Resource.class). The data members (Fields) use @ValueMapValue annotations.

In this example, the lines data member is populated with the component dialog and then written out in the front-end of the HTL component. The getNumLines simply prints a log message and returns a value. This method is invoked by application logic in the HTL front end using this code: 

Number of Lines: ${model.numLines}

Note:

These Java files are added to the Core project later in this article. This is required so the Multiline HTL component works properly. That is, these files have to be in an OSGi bundle and in an Active mode for the Multiline HTL component to work properly. 

Notice the node under the component named cq:dialog. This represents the components dialog. The following code represents the 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="nt:unstructured"
    jcr:title="Title"
    sling:resourceType="cq/gui/components/authoring/dialog"
    helpPath="https://www.adobe.com/go/aem6_2_docs_component_en#Title - HTL">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/foundation/container">
        <layout
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
            margin="{Boolean}false"/>
        <items jcr:primaryType="nt:unstructured">
            <column
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/foundation/container">
                <items jcr:primaryType="nt:unstructured">
					<lines
					    jcr:primaryType="nt:unstructured"
					    sling:resourceType="granite/ui/components/foundation/form/multifield"
					    fieldLabel="Lines">
					    <field
					        jcr:primaryType="nt:unstructured"
					        sling:resourceType="granite/ui/components/foundation/form/textfield"
					        name="./lines" />
					</lines>
                </items>
            </column>
        </items>
    </content>
</jcr:root>

Add the Java files to the Core project

To successfully get the Multiline component to work within AEM, you need to get the MultilineModel Java file into an OSGi bundle and deployed. To do this, you need to get this file into the core project, as shown in this illustration. 

Adding the Java files to the Core project

Under the Core project's scr/java/main location, create a package named com.adobe.summit2017.l3845.models.  Next created a class named MultilineModel and copy the code that is shown in this article to this Java class in Eclipse. Add the second class as well. 

Deploy the project to Experience Manager

From within the Eclipse development environment, you can deploy the project to Experience Manager. Before following this procedure, ensure that the Server is started in the Server view. 

To deploy the Lazybones generated project, perform these tasks: 

1. Select example-project in Eclipse Project Explorer.

The Lazybone project in Eclipse

2. Right click example-project and select Run As and then 2 Maven build

Running Maven build from within Eclipse

3. In the next dialog screen, configure Maven to build the project and deploy it to Experience Manager. Set the Goals field to install and then the profiles field to autoInstallPackage (One word), as shown below.

Configure Eclipse to deploy the Lazybone project to Experience Manager

4. Click Run. If everything occurs as expected, you will see the Eclipse log confirming that the build was succcessful, as shown in the following illustration. 

A log message confirming that the build was successful

OSGi bundle is in Active state

When you deployed the project, the Java classes under the Core project are automatically placed into an OSGi bundle and placed into an Active state, as shown in the following illustration. This means that the Multiline component that uses the Java classes works. If this OSGi bunlde is not in an Active state, then the Multiline component will not successfully work.

The OSGi bundle that contains the Java files is in an Active state.

Note:

You can view the Felix console at http://localhost:4502/system/console

Use the Components in the We Retail site

You can use the components that your imported into Experience Manager from the Lazybones project in an Experience Manager site.  In this article, the components are used in the We Retail example site. 

The Experience Manager We Retail site

Note:

To perform the tasks described in this section, you must successfully deploy the project to Experience Manager. 

Check the components in the Experience Manager JCR

Ensure that the components are located at the following JCR location: 

/apps/my-aem-project/components/content/snippets

If these nodes are not at this location, you have not successfully imported the Lazybone project. 

The components located in the Experience Manager JCR

Configure Experience Manager to allow the components to be used in We.Retail

Configure Experience Manager to let the components defined in the Lazybone project to be used in the We Retail site by performing these tasks: 

1. Open CRXDE lite at http://localhost:4502/crx/de/index.jsp.

2. Navigate to the following path: /conf/we-retail/settings/wcm/policies/wcm/foundation/components/responsivegrid/we-retail-default.

3. Add group:Summit.L3845 to the components multi-value property.

4. Click the Save button. 

Configuring Experience Manager

Note:

If you do not specifiy group:Summit.L3845 exactly in the components property, then your custom components will not drop successfully onto the We.Retail pages. For example, if you put only Summit.L3845, then you will not be able to drop the components onto a We.Retail page. 

Use the components in the We Retail site

You can use the simple and multiline components in the We Retail site. Open the We.Retail site in your AEM author instance by browsing to:

http://localhost:4502/sites.html/content/we-retail

Navigate to We.Retail, United States, English by clicking on the page title (not the page thumbnail).

Navigating the We Retail site

Select the Equipment page by clicking on the thumbnail and then click Edit (Top toolbar).

 

Opening the Equipment We Retail page

Now you will be able to edit the Equipment page in the author instance. You can add the simple and multiline components to this site. 

The Equipment page open in Edit mode

Note:

If you do not see the Side Panel, click the Toggle Side Panel button at the top left to show the side panel. Also, ensure that the page is open in Edit mode and that you select the Summit.L3845 from the Drop-down section in the Components view, as shown in the previous illustration. 

Simple component

Drag the Simple component from the Experience Manager Side Rail onto the page, as shown in the following illustration. 

Drag the Simple component

Right click on the component and select the wrench icon. This causes the dialog to appear. Enter text and then click the check mark icon.

The Simple node dialog

Notice that the text you enter into the dialog is rendered in the We Retail page, as shown in this illustration.

The Simple component is displayed in the Equipment page

Multiline component

Drag the Multiline component from the Experience Manager Side Rail onto the page, as shown in the following illustration.

Dragging the multiline component onto the We Retail page

Right click on the component and select the wrench icon. This causes the dialog to appear. Click the Add button and enter text. Repeat this serveral times and then click the check mark icon.

Adding text in to the multifield dialog

Notice that the text that you entered is now displayed on the We Retail page. 

 

The multiline text is displayed in the We Retail page

Note:

If the OSGi bundle is not in an Active state, then the multiline component will not work. 

Create Proxy components based on Experience Manager Core components

Adobe Experience Manager core components are new components built with HTL and include the following components:

Page authoring components:

  • Page component
  • Breadcrumb component
  • Title component
  • Text component
  • Image component
  • List component
  • Sharing component
  • Form components:

Form container components: 

  • Form text field
  • Form options field
  • Form hidden field
  • Form button

The Core components are located at the following JCR location: 

/apps/core/wcm/components

In this section, you can create Proxy components that are based on Experience Manager core components and make them available within your project. A Proxy component's sling:resourceSuperType references a corresponding core component (as shown in this section).

The reason why you create proxy components is because if you want to make a change to the component's application logic, then it is recommended that you make a change to the proxy component as opposed to the Core component. 

Note:

Experience Manager Core Components are only available if the sample content is included. If they are not included in your Experience Manager instance, you can get them from GitHub at the following URL.

https://github.com/Adobe-Marketing-Cloud/aem-core-wcm-components

Also the version core/wcm/components/text/v1/text is the version bundled with We.Retail

Create a Text Proxy component

You can create a text proxy component that is based on the core Text component and make it available within your project. To start, switch to Eclipse. In the Project Explorer view, open the example-project.ui.apps project and open up my-project\ui.apps\src\main\content\jcr_root\apps\my-aem-project\components\content\snippets.

Location to where to add Core Components

Right click on the content folder and select New and then Node.

Create a new Node in Eclipse

Note:

If you get a message box stating that node types cannot be verified, click the Continue (do not ask again) button.
 

In the New Node dialog box, provide text as the node name and cq:Component as the node type. Click the OK button.

Specify the type of Node

In the bottom pane, switch to the Properties view and click on the JCR Properties tab. Click on the newly created text node to display the properties in the Properties view.

The Properties view that can be viewed from Windows, Show View, Properties

Right-click inside the Properties view and select Insert from the context menu. Double-click in the newly created row and set the Name to componentGroup and the Value to Summit.L3845 (the value used for all components in this article). .

Repeat this two more times with the following values.

  • jcr:title (String) - Text
  • sling:resourceSuperType (String) - core/wcm/components/text/v1/text

You can verify if this component was successfully created by viewing the project in CRXDE lite. First deploy this project to Experience Manager by running as a Maven command (as discussed earlier in this article).

If the project is successfully deployed, then the component can be viewed in CRXDE lite, as shown in this illustration.

The custom Text component based on Core Components in CRXDE lite

Note:

If you experience issues setting properties for the Core components in Eclipse, then you can set the properties directly in CRXDE lite at this path: /apps/my-aem-project/components/content/snippets.

Create a Title Proxy component

Repeat the same process for the title component. Name the node title with the node type of cq:Component and specify these properties:

  • componentGroup (String) - Summit.L3845
  • jcr:title (String) - Title
  • sling:resourceSuperType (String) - core/wcm/components/title/v1/title

Create an Image Proxy component

Repeat the same process for the image component. Name the node image with the node type of cq:Component and specify these properties:

  • componentGroup (String) - Summit.L3845
  • jcr:title (String) - Image
  • sling:resourceSuperType (String) - core/wcm/components/image/v1/image

Add some configuration information

To enable drag-and-drop behavior for the image component (so an image asset is dragged into the page), you need to perform a few extra steps. First, with the image node selected, right-click in the JCR Properties view and select Show in editor. This action opens the XML representation of this node in the Eclipse editor and Outline view. In the Outline view, right click on the jcr:root entry and select Edit Namespaces.

Edit namespace

In the Edit Schema Information dialog, click the Add button. Select Specify New Namespace. As the Prefix, enter cq. As the Namespace Name, enter http://www.day.com/jcr/cq/1.0. Click the OK button.

Back in the Edit Schema Information dialog, click the OK button. Click the Save icon. Next, select the image node and create a new node inside it (right-click, select New, then Node). Enter cq:editConfig as the node name and cq:EditConfig as the node type.

A cq:editConfig node

Note:

These values are different only by a single casing change. Be careful.

In the XML editor in Eclipse, select the line which reads
<cq:editConfig jcr:primaryType="cq:EditConfig"/>

Replace this line of code

Replace this line of code with the following code. Then save the file. 

<cq:editConfig jcr:primaryType="cq:EditConfig">
        <cq:dropTargets jcr:primaryType="nt:unstructured">
            <image jcr:primaryType="cq:DropTargetConfig" accept="[image/.*]" groups="[media]"
                    propertyName="./fileReference">
                <parameters jcr:primaryType="nt:unstructured" imageCrop=""
                    imageMap="" imageRotate=""
                    sling:resourceType="my-aem-project/components/content/image"/>
            </image>
        </cq:dropTargets>
        <cq:inplaceEditing jcr:primaryType="cq:InplaceEditingConfig" active="{Boolean}true"
            editorType="image">
            <config jcr:primaryType="nt:unstructured">
                <plugins jcr:primaryType="nt:unstructured">
                    <crop jcr:primaryType="nt:unstructured" features="*"/>
                    <flip jcr:primaryType="nt:unstructured" features="-"/>
                    <map jcr:primaryType="nt:unstructured" features="*"/>
                    <rotate jcr:primaryType="nt:unstructured" features="*"/>
                    <zoom jcr:primaryType="nt:unstructured" features="*"/>
                </plugins>
                <ui jcr:primaryType="nt:unstructured">
                    <inline jcr:primaryType="nt:unstructured"
toolbar="[crop#launch,rotate#right,history#undo,history#redo,fullscreen#fullscreen,control#close,control#finish]">
                        <replacementToolbars jcr:primaryType="nt:unstructured"
                            crop="[crop#identifier,crop#unlaunch,crop#confirm]"/>
                    </inline>
                    <fullscreen jcr:primaryType="nt:unstructured">
                        <toolbar jcr:primaryType="nt:unstructured"
left="[crop#launchwithratio,rotate#right,map#launch,flip#horizontal,flip#vertical,zoom#reset100,zoom#popupslider]"
                            right="[history#undo,history#redo,fullscreen#fullscreenexit]"/>
                        <replacementToolbars jcr:primaryType="nt:unstructured">
                            <crop jcr:primaryType="nt:unstructured"
                                left="[crop#identifier]"
                                right="[crop#unlaunch,crop#confirm]"/>
                            <map jcr:primaryType="nt:unstructured"
                                left="[map#rectangle,map#circle,map#polygon]"
                                right="[map#unlaunch,map#confirm]"/>
                        </replacementToolbars>
                    </fullscreen>
                </ui>
            </config>
        </cq:inplaceEditing>
    </cq:editConfig>

Note:

Deploy the project to Experience Manager using the procedure specified in this article. 

Use the Core Components in the We Retail site

After you deploy the project to Experiene Manager, the Core components that you built using Eclipse are avaible to your project. The following illustrations shows these components in the side rail. 

The We Retail site with the Core Components displayed

Drag the image component into the We Retail page. Then open the dialog and drag an asset onto the dialog as shown below. 

Drag an asset onto the Image dialog

Click the checkmark button in the dialog. Now the image appears in the We Retail page.  

See also

Join the AEM community at: Adobe Experience Manager Community

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy