Sie sind auf Seite 1von 124

Adobe Experience Manager Developer Guide

Adobe Experience Manager


Developer Guide

Revision History

Version No. Date Prepared by / Modified by Significant Changes


1.0 JAN 2019 Pratapareddy K Initial Draft

Design Sign Off

Accepted By Date

1
Adobe Experience Manager Developer Guide

Table of Contents

AEM INTRODUCTION: .......................................................................................................................... 5


Webserver - AEM: ................................................................................................................................ 7
Author and Publish INSTANCES: .......................................................................................................... 7
Views in AEM: ....................................................................................................................................... 8
Technology Stack of AEM – OVERVIEW:.............................................................................................. 8
Create Structure of Website in AEM:............................................................................................. 10
Create a Template using crxde for your website: .......................................................................... 11
Create a Page Rendering Component:............................................................................................ 14
Create Pages in AEM: ...................................................................................................................... 16
Create a Project Structure: .............................................................................................................. 18
Creating a Template in AEM: ......................................................................................................... 18
Creating a Touch UI Component in AEM: .......................................................................................... 19
Testing Newly Created Touch UI Component: .............................................................................. 20
Basic Trouble Shooting in Touch UI: .............................................................................................. 21
Create Custom Component in CQ5 with Custom DIALOG: ............................................................... 22
Integrate Custom Component with the Page: ................................................................................ 29
Clientlibs in AEM: ............................................................................................................................... 30
Step 1: Creating components and ClientLib nodes ............................................................................. 30
Step 2: Adding JavaScript and CSS resources .................................................................................... 31
Step 3: Using ClientLibs in your component ....................................................................................... 33
Step 4: Merging files ........................................................................................................................... 34
Step 5: Dependencies ......................................................................................................................... 34
Step 6: Minify and Gzip ....................................................................................................................... 35
Sightly in AEM: ................................................................................................................................... 35
Sightly Implicit Objects:....................................................................................................................... 40
Component Development Sightly vs JSP............................................................................................. 43

2
Adobe Experience Manager Developer Guide

Sling Models in AEM........................................................................................................................... 44


Sling Model Annotation ..................................................................................................................... 45
Use Sling Model with SIGHTLY: -........................................................................................................ 48
Create Sling models and use them on components using Sightly .................................................... 50
Schedulars in AEM (Scheduler Service): ............................................................................................ 55
Scheduling with a cron expression :.................................................................................................... 55
Preventing concurrent execution ....................................................................................................... 57
Scheduling the job just once in a cluster ............................................................................................ 57
scheduled jobs registered through the scheduler API : ....................................................................... 57
Defining the job................................................................................................................................... 58
Scheduling with a cron expression...................................................................................................... 58
Scheduling at periodic times ............................................................................................................... 58
Scheduling at a given time .................................................................................................................. 58
A service scheduling the job based on 3 different kinds of scheduling .............................................. 59
Sling Servlets in AEM: ......................................................................................................................... 61
Sling Servlet using path ....................................................................................................................... 61
Ajax call that you can use to call this servlet using Rest API: ................................................... 66
Sling Servlet using a resource type and selector ................................................................................ 67
Ajax call that you can use to call this servlet using Rest API: ................................................... 72
Advantages of registering servlet using selector over path: .............................................................. 73
Sling Servlet Best Practices: ................................................................................................................ 74
OSGI Services in AEM: ........................................................................................................................ 78
What is a service factory? ................................................................................................................... 78
What can services be used for? .......................................................................................................... 79
How are services accessed? ................................................................................................................ 79
Releasing services ............................................................................................................................... 80
Best practices for accessing OSGi services .......................................................................................... 80
The white-board model ...................................................................................................................... 83
Workflows in AEM .............................................................................................................................. 86
Workflow Models ............................................................................................................................... 86

3
Adobe Experience Manager Developer Guide

Workflow Nodes ................................................................................................................................. 89


Workflow Launchers: .......................................................................................................................... 93
Content Fragments in AEM ................................................................................................................ 95
Create a Content Fragment ................................................................................................................ 97
Edit Text within the Content Fragment .............................................................................................. 99
Create a Variation ............................................................................................................................. 100
Associate an Asset Collection to a Content Fragment ...................................................................... 102
Set Content Fragment Metadata ...................................................................................................... 104
Use a Content Fragment in a web page ............................................................................................ 105
Open the web page in the Page Editor ............................................................................................. 106
Add a Content Fragment in the page ................................................................................................ 107
Use Associated Assets ....................................................................................................................... 109
Experience Fragment in AEM ........................................................................................................... 112
When Should You Use Experience Fragments? ................................................................................ 112
Creating an Experience Fragment ..................................................................................................... 113
Editing your Experience Fragment .................................................................................................... 115
Creating An Experience Fragment Variation..................................................................................... 116
Using your Experience Fragment ...................................................................................................... 118
Building Blocks .................................................................................................................................. 120
The Plain Rendition ........................................................................................................................... 123

4
Adobe Experience Manager Developer Guide

AEM INTRODUCTION:

Adobe Experience Manager (AEM), is a comprehensive content management platform solution for
building websites, mobile apps and forms - making it easy to manage your marketing content and assets

AEM is a component of the Adobe Marketing Cloud, which is a suite of solutions that integrate with AEM
such as Adobe Target, Adobe Analytics, Adobe Campaign, Adobe Social, Adobe Primetime, Adobe Media
Optimizer and Adobe Audience Manager. You can use AEM alone, or in conjunction with one or more of
the other components for a complete digital marketing solution.

History of AEM:

CQ5 is a version of Day CQ portfolio developed by a Swiss-based software company Day Software in
2008, followed by Day CQ 3.5, 4.0, 4.1 and 4.2. Adobe Systems renamed Day CQ5 as Adobe CQ5 after
acquiring Day Software in 2010. Following the release of the fifth version of CQ5 i.e., 5.5, Adobe
renamed it as Adobe Experience Manager (AEM) in 2013 with a sixth version AEM 5.6, Latest version is
6.4.

5
Adobe Experience Manager Developer Guide

Reference:

https://helpx.adobe.com/in/experience-manager/aem-previous-versions.html

Can obtain the documentation of previous versions.

Installation of Author and Publish Instances

a. Pre-requisite: Installed Java Platform, Standard Edition JDK - or other supported Java Virtual Machines.

b. Go to command prompt and check whether Java installed/Configured in environmental variables.

cmd->java -version JAVA_HOME -> JDK path, path ->JDK/bin

Experience Manager Quick-start file (Standalone JAR or web-application deployment WAR – Without build
in servlet engine / server).

Naming Convention before installing AEM instance:

When first installing AEM or CQ, the name of the quickstart jar can be used to determine whether the
instance uses the author run mode or the publish run mode.

The naming convention to use for CQ 5.6 and earlier is:

cq-<optional-version-or-identifier>-<standard-run-mode>-<port-number>

The naming convention to for AEM 5.6.1 and later is:

aem-<optional-version-or-indentifier>-<standard-run-mode>-<port-number>

As an example, the quickstart jar for an AEM 6.0 instance running as an author instance with the port of
4502 could be named:

aem-6.0.0.20140515-author-4502.jar or aem-author-p4502

Reference: https://helpx.adobe.com/experience-manager/kb/RunModeSetUp.html

Different Ways to start AEM Instance:

1. Double Click on Jar file.


2. Java command to execute Jar

6
Adobe Experience Manager Developer Guide

java -Xms512m -Xmx2048m -XX:MaxHeapSize=1024m -Xdebug


Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=30303 -jar AEM-author-p4502.jar

Note: As we know Java allocate objects at heap area, sometime it happens we get the ‘Out of memory’
exception, using above command helps in allocating the extra space to heap so that we can avoid
memory exceptions.

Also, we can bind the debug port, it helps in debugging the issues with Java Bundles/Code.

Once the file is extracted using option-1, it can be started by going

crx-quickstart folder -> bin -> Start.bat (Unix compatible command also can be found)

Stop.bat ->Stop file.

WEBSERVER - AEM:

Once AEM instance is started, A webserver is also get started at the back end.

Apache Jetty - Internal implementation of AEM comes default. – It’s a servlet engine and HTTP Server.

More info: https://www.eclipse.org/jetty/

If needed, different application server can be configured like JBoss/WebLogic – AEM War file is required.

AUTHOR AND PUBLISH INSTANCES:

Author:

Author is usually located behind the internal firewall as it is the environment where you and
your colleagues will input your content and administrate the system

Publish:

This environment holds the content you have made available to visitors to
your website; be it public, or within your intranet

7
Adobe Experience Manager Developer Guide

VIEWS IN AEM :

Classic UI -> http://localhost:4502/welcome.html

Legacy UI, Extended JS implementation, Not compatible for devices i.e. Unresponsive

Touch UI -> http://localhost:4502/aem/start.html

Touch -> Coral UI and Granite UI based, responsive and mobile first.

WCM Authoring UI mode Service. (Can change the behavior while opening the page in content or site
admin), Modes (TOUCH & CLASSIC)

ROOT Mapping: /welcome.html /projects.html

TECHNOLOGY STACK OF AEM – OVERVIEW:

8
Adobe Experience Manager Developer Guide

• JCR (Content Repository API for Java): It can be defined as the specifications for accessing content
repository using JAVA API in uniform manner. So, JCR is “type of repository”. CRX is an Adobe
implementation of JCR. Similarly, Apache Jackrabbit is an external implementation of JCR by apache.
Example of traditional Databases – Oracle/SQL Server – Table Concept.

Some important Points:

A JCR is an object database that provides various services for storing, accessing, and managing content.

In addition to a hierarchically structured storage, common services of a content repository are versioning,
access control, full-text searching, and event monitoring (JCR Observation Framework - Event Handling
(Modified / Added etc.)

The JCR provides a generic application data store for structured hierarchical data, plus observation,
versioning and full text search.

JCR stores data in form of (Nodes -> Properties (Key/Value)), it forms the hierarchical data model.

• Entire Site data gets stored in form of Node and Properties.

• Every File, Folder, Image treats as a node. To differentiate, there is an jcr: primaryType [sling:folder,
nt:folder, etc.]

• Each node will be having jcr: primaryType property and every page would be having a child node
jcr:content, every page will be of type cq: page under content.

• Open JCR node, and see in property console (Protected, Mandatory, Multiple, Auto Created]

• Data is stored in form of TAR (Tape Archive files. (Unix compressed files – Non-readable format)

• Data will be lost if any segment is deleted.

• Tar Location under crx-quickstart/repository/segments

To view the repository:

http://localhost:4502/crx/de

http://localhost:4502/crx/explorer

9
Adobe Experience Manager Developer Guide

Sling:
Apache Sling is a web application framework for content-centric applications, using a Java Content
Repository, such as Apache Jackrabbit or CRX, to store and manage content:

• is based on REST principles to provide easy development of content-oriented applications.

• is embedded within CQ5.

• is used to process HTTP rendering and data-storage requests which assemble, render and send the
content to a client.

• maps Content objects to Components (which render them and process incoming data).

• comes with both server-side and AJAX scripting support.

• can be used with a range of scripting languages, including JSP, ESP and Ruby.

• started as an internal project of Day Management.

• has been contributed to the Apache Software Foundation

OSGI
CQ5 is built within an application framework which is based on the OSGi Service Platform.

OSGI Technology:

• It is the dynamic module system for Java™.

• It provides the standardized primitives that allow applications to be constructed from small, reusable
and collaborative components. These components can be composed into an application and deployed.

• OSGi bundles can contain compiled Java code, scripts, content that is to be loaded in the repository,
and configuration or additional files, as needed.

CREATE STRUCTURE OF WEBSITE IN AEM:


In this section, we will create a directory structure for the website. Follow below steps to create
directory structure for website in AEM (CQ5):

1. Login into CRXDE Lite. In left panel, navigate to the apps folder.
2. Right click on apps folder. Select Create and Create Folder.

10
Adobe Experience Manager Developer Guide

3. Enter the name as training(This will be your project name) and click OK.
Tip:- Always provide node name in lower case, because they become part of the URL.

4. click Save All.

+
5. Repeat the above process to create a directory structure as follows:

Your basic structure of website is completed.

CREATE A TEMPLATE USING CRXDE FOR YOUR WEBSITE:


A template is used to create a page. To create a page, the template’s content (apps/<application
name>/templates/<template name>) must be copied to corresponding position in site tree. This
happens automatically when we create a page using AEM.
When we create a template, following information gets saved at node repository:

 Label: cq:Template – node name


 Title: jcr:title – property
 Resource Type: sling:resourceType – property
 Ranking: ranking – property
 Allowed Paths: allowedPaths – property

11
Adobe Experience Manager Developer Guide

In this section, we will create a template in AEM:

1. Right click the templates folder created in previous section.


2. click Create > Create Template
3. Enter following details and click Next:
Name Value

Label myTemplate

Title Content Page Template

Description This is Simply Cracked Content page template

Resource training/components/myComponent( We need to create a component with


Type same name “myComponent“)

1(ranking indicates the order in which the template appears on the creation
page. Setting rank to 1 ensures that the template appears first in the list.When
Ranking we create a page from site admin)

4. Click the + symbol prided with Allowed Path property. The Allowed Path property defines the
path where this template is to be used to create pages. Add the following value : /content(/.*)?

12
Adobe Experience Manager Developer Guide

5. click Next on the Allowed Parent screen.


6. click OK on the Allowed children screen.
7. click Save All.
Note: Test the template created.

 Go to Site http://localhost:4502/sites.html/content
 On the toolbar-> click Create -> select Create Page.

13
Adobe Experience Manager Developer Guide

 See the template created.

 click Cancel to close the Window.

CREATE A PAGE RENDERING COMPONENT:


1. Right click the /apps/training/components folder and click Create -> Create Component.
2. Enter following details.
Note: The Label name should be same as the resource type that we have given at the time of
creating Template.

14
Adobe Experience Manager Developer Guide

Name Value

Label myComponent

Title My Custom Component

Description This is Simply Cracked Content Page Component

3. Click Next until you reach till last screen. Click OK and click Save All changes.
4. Notice that the myComponent component is created with a default jsp with the same name as
component name myComponent .jsp
5. Double click on myComponent .jsp and replace the jsp code with below code.
1<html>

2<%@include file="/libs/foundation/global.jsp" %>

3<cq:include script="/libs/wcm/core/components/init/init.jsp"/>

4<head><title>Welcome to Simply Cracked </title></head>

5<body>

6<h1>Welcome to Simply Cracked</h1>

7<h2>I am your rendering script!!</h2>

8<cq:include path="par" resourceType="foundation/components/parsys" />

9</body>

10</html>

6. You have successfully created a page-rendering component.


Note:- global.jsp is used to include default scripts and libraries whereas init.jsp is used to
display sidekick in authoring.

15
Adobe Experience Manager Developer Guide

CREATE PAGES IN AEM:

A page is a place where author create and edit content, which will be viewed by site visitors in
publish mode.
In this section we are going to create a basic structure of website and pages in aem.

1. Log in to AEM SiteAdmin.


2. Click Websites in the left panel.
3. Create a folder Click -> New -> New Folder -> Enter name as Simply Cracked.

4. Click New -> New Page.

16
Adobe Experience Manager Developer Guide

5. Enter the title of the page as Home page( This will be our jcr:title ) .

6. Enter Name as homepage


Tip: Always provide name in lower case as this will be a part of url.
7. Select Content Page Template as Template and click Create.
8. As soon as we create a page siteadmin will push our new page to content folder in crxde.
9. Double click on Home Page to open it. By default it will open in Touch UI. Move to classic UI
by replacing editor.html with cf# in url.
10. The page will look like a below.

You have successfully rendered the component on Template.

17
Adobe Experience Manager Developer Guide

CREATE A PROJECT STRUCTURE:

Your Project Structure should look like below image:

CREATING A TEMPLATE IN AEM:

Follow below steps to create a Template in AEM.


 Select Template Folder. Right Click and select create template.
 Enter below details in create template dialog.

 Enter Allowed Path: /content(/.*)?


 Click Next. Click Finish and Save Changes.

18
Adobe Experience Manager Developer Guide

CREATING A TOUCH UI COMPONENT IN AEM:

Follow below steps to create redirect component:


 Select Components Folder. Right Click and select create component.
 Enter below details in create component dialog.

Note:- Entering Super Type is not mandatory in case of classic UI, but for opening a page in
touch ui it is mandatory to provide Super Type, JCR internally convert it to
sling:resourceSuperType.
 Click Next. Click Finish and Save Changes.
 Double click on touchComponent .jsp and replace the jsp code with below code.
1<html>

2<%@include file="/libs/foundation/global.jsp" %>

3<cq:include script="/libs/wcm/core/components/init/init.jsp"/>

4<body>

5<h1>Here is where your Touch UI component will go</h1>

6<cq:include path="par" resourceType="foundation/components/parsys" />

7</body>

8</html>

19
Adobe Experience Manager Developer Guide

Note: - Make sure that if you are creating a page component. It’s sling:resourceSuperType is set to
/foundation/components/page as It inherits both dialog and cq:dialog. Which will solve both the
editor.html and page properties issues.

TESTING NEWLY CREATED TOUCH UI COMPONENT:

Now let’s test our newly created Touch UI component. Follow below steps to test component in
AEM:
 Go to Site Admin.
 Create a New Folder to maintain readability of Project.
 From Top Bar Select New –> New Page.
 Enter Page Name
 Select Template(Touch UI Template)
 Double click on the Page.

 By default Page will open in Touch UI if you are using AEM 6 or above.

20
Adobe Experience Manager Developer Guide

Note:- You can always change default authoring environment either to classic UI or Touch UI

 If no components are visible after opening page in Touch UI.

BASIC TROUBLE SHOOTING IN TOUCH UI:

 If blank/white page is opening in touch ui, make sure that you have added Super Type at the
time of creation of the component or sling:superResourceType is present on component Node.
 add sling:superResourceType as parbase if you to inherit attributes from other components.
Like if you want your component to be authorable and draggable add parbase to it.So that they
can inherit the image and text rendering properties when added to a Paragraph system

21
Adobe Experience Manager Developer Guide

CREATE CUSTOM COMPONENT IN CQ5 WITH CUSTOM DIALOG:


Components are re-usable, modular units used to achieve specific functionality that can be present on
webpage. The main advantage of having a component is it is modular and isolated individual units
that can be reused across the application. Below are the general properties of a component.

Now the next question that arises in our mind by looking at above component is what does
allowedPaths property do or what do we mean by sling:superResourceType.Let’s see

 allowedParents: It specifies path of a component that is allowed to be a parent of this


component.
 allowedChildren: It specifies path of a component that is allowed to be a child of this
component.
 componentGroup: It specifies group under which the component can be selected in the
Sidekick.
 sling:resourceSuperType: It is used to achieve inheritance in cq. When set, it inherits the
specified component to this component.
There are two approaches for creating a custom component in adobe cq: -

 By copying component from libs folder and then renaming it.


 By creating a new component and then point it to libs-> foundation component.
Note: - I will suggest to use second approach as chances of manual copy pasting error are less, but
for experienced developers i suggest first approach as it save lots of time while creating
component. Let’s see both Approaches:
Steps to create custom component in CQ5: -
Approach 1:
 Open CRXDE Lite , create a component folder in apps/<myProject> copy an existing
component to it, such as the Text component, and rename it( Like customText in below
example).For example, to customize the Text component copy:

22
Adobe Experience Manager Developer Guide

 Text component from /libs/foundation/components/text to /apps/myProject/components/text

 Change the jcr:title of new component (Like Custom Text Component in above example), so
that we can easily distinguish it.
 In CQ WCM , open a page in your web site in authoring mode you can see new component is
available in the side kick under the component group that you have specified.

Approach 2:
Here we will create a custom component with custom dialog, which will have three fields in its
dialog.
 Open CRXDE Lite , create a component folder in apps/<myProject>.
 Right click on components folder Select Create –> Create Components.

 Enter below details in the Create Component dialog :


Label : customLinkComponent
Title : Custom Link
Description : Custom Link Component, used by my Sample Website
Super Type : foundation/components/page

23
Adobe Experience Manager Developer Guide

Group: Geometrixx Gov

 Click Next till last screen and click OK on last Screen. These screen contains optional
properties which we have already seen above.

 Click on Save All on top left of crxde to save the changes.


Use of Advanced Component Setting during creation of component in AEM:-
 Is Container: Enable to make you component as a container like parsys. Where content author
can drag and drop other components.

24
Adobe Experience Manager Developer Guide

 No Decoration: When we hover on our component in authoring enviroment a green border


comes, if we dont want the green border selection we can enable No decoration
 Cell Name: A unique div id that will be assigned to your component div.
 Dialog Path: Path of existing dialog that you want to reuse.
Now Lets create a Custom Dialog for the Custom Link Component
 Right Click on customLinkComponent that we have created Select Create –> Create Dialog.

 Enter below details in the Create Dialog :


Label: dialog
Title: Custom Link Dialog

25
Adobe Experience Manager Developer Guide

 Click OK and save all changes. You can see that your dialog structure has created.

 Provide a suitable name to tab1 value(For Ex: I have provided Custom Link Tab) and save
changes.

 Right Click on tab1 or Custom Link Tab and create a node by Selecting Create –> Create Node
of type cq:WidgetCollection.
 Enter below details in the Create Node:
Name: Items
Type: cq:WidgetCollection
Note:- name of cq:WidgetCollection should be Items.

 Create new node inside the componentItems node which we have just created and enter
below details. Save the changes. your dialog structure would look like below figure.

26
Adobe Experience Manager Developer Guide

Name: displaytext
Type: cq:Widget

 Add following properties manually (fieldDescription, fieldLabel, name, xtype) for the
customDisplayText node to configure it as a text field. see below figure for reference.

 Similarly create two more nodes on the same level of customDisplayText with
properties shown below:
Name: link
Type: cq:Widget

Name: newWindow

27
Adobe Experience Manager Developer Guide

Type: cq:Widget

 Save the changes and your final folder structure should look like:

 Open customLinkComponents.jsp and replace the existing code with below code.

1<%@page language="Java"%>

2<%@include file="/libs/foundation/global.jsp"%>

3<cq:include script="/libs/wcm/core/components/init/init.jsp"/>

4<%@page session="false" %>

5<% // TODO add you code here %>

6<html>

7<head>

8<title>Link Components</title>

9</head>

28
Adobe Experience Manager Developer Guide

10<body>

11<a href="#" >Click Here</a>

12</body>

13</html>

INTEGRATE CUSTOM COMPONENT WITH THE PAGE:


 Create a Page or use existing page and make sure you have sidekick in it which contains
your custom link component.

 Drag the custom link component to page and double click on the link to view the dialog.

29
Adobe Experience Manager Developer Guide

CLIENTLIBS IN AEM:

The AEM Client Library (or ClientLib) functionality will manage all your JavaScript and
CSS resources in your application. It takes cares of dependency management, merging files
and minifying content (removing unnecessary white spaces).

The following application scenarios will be explained:

 multiple components with their own JavaScript and CSS files


 CSS resources have to go in the <head>, JavaScript resources at the end of the
page
 Resources need to be minified
 changing the minification engine

Let’s get started!

STEP 1: CREATING COMPONENTS AND CLIENTLIB NODES

First we make a few components, in this example 3 components are used, we do this all via
CRXDE-lite (http://localhost:4502/crx/de).

Next we are going to add a “clientlib” node of type “cq:ClientLibraryFolder”, inside this
node the JavaScript and CSS resources are stored.

30
Adobe Experience Manager Developer Guide

Add a property to every “clientlib” node called “categories” of type String[] with the single
value of “myproject.components” (to get a String[] type click the “Multi” button).

Now add a Boolean property “allowProxy”, and set this to true. This will make the clientlibs
available via the url /etc.clientlibs/, so it means they are not having the /apps reference.

Your components-folder will look now like this:

STEP 2: ADDING JAVASCRIPT AND CSS RESOURCES


Now we are going to add some simple JavaScript and CSS resources in the “clientlib” nodes.

31
Adobe Experience Manager Developer Guide

Create following files inside of your “clientlib” folder of “MyFirstComponent”:

first.css

.firstContainer {

margin-top:10px;

first.js

/*

* This is the comment of the function

*/

function getNameFirst() {

// return the name

return "some value";

js.txt

# mentions all the JavaScript resources of the ClientLib

first.js

css.txt

# mentions all the CSS resources of the ClientLib

first.css

And repeat the same thing for the other components to achieve something that looks like this:

32
Adobe Experience Manager Developer Guide

The configuration of the components are now finished.

STEP 3: USING CLIENTLIBS IN YOUR COMPONENT

Now the setup of the ClientLib is finished we can invoke the ClientLibs in your page compo-
nents. When you are using a JSP you can use cq:includeClientlib . In case you are using the
HTML Template Language (HTL), you can use the data-sly-call to invoke the ClientLib. In
this article HTL will be used for the examples.

We start with putting the following into the <head> element of our page:

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html" />

<sly data-sly-call="${clientlib.css @ categories='myproject.components'}" />


<sly data-sly-call="${clientlib.js @ categories='myproject.components'}" />

The value of the “categories” properties of the “clientlib” nodes are


“myproject.components”, which is what we need to provide above.

This results in the following HTML-output:

33
Adobe Experience Manager Developer Guide

<link rel="stylesheet" href="etc.clientlibs/mycomponents/MyThirdComponent/clientlib.css" type="text/css">

<link rel="stylesheet" href="etc.clientlibs/mycomponents/MySecondComponent/clientlib.css" type="text/css">

<link rel="stylesheet" href="etc.clientlibs/mycomponents/MyFirstComponent/clientlib.css" type="text/css">

<script type="text/javascript" src="etc.clientlibs/mycomponents/MyThirdComponent/clientlib.js"></script>

<script type="text/javascript" src="etc.clientlibs/mycomponents/MySecondComponent/clientlib.js"></script>

<script type="text/javascript" src="etc.clientlibs/mycomponents/MyFirstComponent/clientlib.js"></script>

This has a few downsides:

 6 server calls have to be made to fetch the resources.


 Application structure is exposed.

STEP 4: MERGING FILES

To merge the several clientlib files into one, we define a clientlibs that is embedding the oth-
er categories. Example here is taken from /apps/weretail/clientlibs/clientlib-base.

STEP 5: DEPENDENCIES

Another property you can add to the “clientlib” node is “dependencies”, this way you can
define dependencies between ClientLibs.
Let’s add a dependency on “cq.jquery”:

When you now reload the page the dependency is written:

34
Adobe Experience Manager Developer Guide

<script type="text/javascript" src="https://blogsimages.adobe.com/etc/clientlibs/foundation/jquery.js"></script>

<script type="text/javascript" src="https://blogsimages.adobe.com/etc.clientlibs/myproject/clientlib.js"></script>

STEP 6: MINIFY AND GZIP

To deliver a better performance you can enable “Minify” and “Gzip” for the “Adobe Gran-
ite HTML Library Manager” (previously also called “Day CQ HTML Library Manager”),
in the Felix Configuration console (http://server/system/console/configMgr). These set-
tings are recommended for production installations.

By default the YUI compressor is used when minifying files, you can better use the GCC
(Google Clojure Compiler) for this.

SIGHTLY IN AEM:

Sightly was introduced by AEM 6.0 to replace JSP by a new HTML Templating System.

Advantages of using Sightly

Below advantages of using Sightly make you to code sightly easier and faster:

 Lightweight – No dependencies, fast and lean.


 Secure – Automatic contextual XSS protection and URL externalization.
 Code-less – Enforce separation of concerns between logic and markup.
 Powerful – Straight-forward API for logic, allowing to do virtually anything.
 Intuitive – Clear, simple & restricted feature set.

35
Adobe Experience Manager Developer Guide

Difference between Sightly vs JSP

Sightly Offers below advantages over JSP for better development in AEM :

 Protection against cross-side scripting injection.


 Easily development of AEM Projects by front-end developers.
 Flexible and powerful templating and logic binding features.
 Strong connection to Sling use case.
 Slightly only Supports HTML5.
 Using sightly components development becomes a part of Web Developer instead of a
java developer.

 Need to write less code in Sightly thus productivity increases.


 Wider range of implicit objects as compared to JSP.

Comments in Sightly:

1 <b><!--/* I am a Sightly Comment */--></b>

Sightly Code:

1 <a href="${properties.link || '#'}" title="${properties.jcr:title}">;

36
Adobe Experience Manager Developer Guide

2 ${properties.jcr:description}

3 </a>

JSP Code:

1 <a href="<%= xssAPI.getValidHref(properties.get("link", "#")) %>"

2 <% String title = properties.get("jcr:title", ""); if (title.length() > 0) {

3 %>title="<%= xssAPI.encodeForHTMLAttr(title) %>"<% } %>>

4 <%= xssAPI.encodeForHTML(properties.get("jcr:description", "")) %>

5 </a>

Building Blocks of Sightly

Sightly Expression Language

1 ${properties.myProperty}

Sightly Block Statements

1 <span data-sly-test="${isVisible}">${text}</span>

Sightly Use-API

1 <span data-sly-use.obj="script.js">${obj.text}</span>

Expression Operators in Sightly

37
Adobe Experience Manager Developer Guide

Sightly Logical operations

1 ${!myVar}

2 ${conditionOne || conditionTwo}

3 ${conditionOne && conditionTwo}

4 ${properties.jcr:title || conditionTwo}

Equality / Inequality (only for same types)

1 ${varOne == varTwo} ${varOne != varTwo}

Comparison (only for integers)

1 ${varOne < varTwo} ${varOne > varTwo}

2 ${varOne <= varTwo} ${varOne >= varTwo}

Sightly Conditional Operator

1 ${myChoice ? varOne : varTwo}

Sightly Grouping Operator

1 ${varOne && (varTwo || varThree)}

Expression Options

Everything after the @ is a parameter

1 ${myVar @ optOne, optTwo}

38
Adobe Experience Manager Developer Guide

2 ${myVar @ optOne='value', optTwo=[1, 2, 3]}

Sightly String formatting (Concatenation)

String concatenation can be done in sightly using @ format

1 <div

2 data-sly-test.concat="${ 'This is page {0}, with title {1}' @

3 format=[currentPage.name,currentPage.title]}">

4 ${concat}

5 </div>

Internationalization in Sightly

1 ${'Page' @ i18n}

2 ${'Page' @ i18n, hint='Translation Hint'}

3 ${'Page' @ i18n, source='user'}

4 ${'Page' @ i18n, locale='en-US'}

Array Join in Sightly

${['one', 'two'] @ join='; '}


1

39
Adobe Experience Manager Developer Guide

SIGHTLY IMPLICIT OBJECTS:

Below are the most frequently used Implicit objects of Sightly:

Sightly Use Statement implicit object

Sightly Use statement: Initializes a helper object.

1 <!--/* template.html */-->

2 <div data-sly-use.nav="navigation.js">${nav.foo}</div>

3 <!--/* navigation.js */-->

4 use(function () {

5 return {

6 foo: "Hello World"

7 };

8 });

Output

<div>Hello World</div>
1

Sightly Unwrap Statement Implicit Object

Slightly UnWrap Statement: Removes the host element while retaining its content

40
Adobe Experience Manager Developer Guide

1 <div data-sly-use.nav="navigation.js" data-sly-unwrap>

2 ${nav.foo}</div>

Output:

Hello World

Sightly Test Statement Implicit Object

Slightly Test Statement object: Conditionally removes the element and its content.

1 <span data-sly-test="${properties.showText}">text</span>

2 <span data-sly-test.abc="${a || b || c}">is true</span>

3 <span data-sly-test="${!abc}">or not</span>

Output:

<span>text</span>
1
<span>is true</span>
2

Sightly List Statement Implicit Object

Sightly List Statement: Repeats the content for each enumerable property.

41
Adobe Experience Manager Developer Guide

1 <ol data-sly-list="${currentPage.listChildren}">

2 <li>${item.title}</li>

3 </ol>

Output:

1 <ol>

2 <li>Triangle Page</li>

3 <li>Square Page</li>

4 </ol>

Get size of list in HTL (Sightly): -

<ol data-sly-list="${currentPage.listChildren}">

1 <li>${item.title} ${currentPage.listChildren.size}</li>

2 </ol>

Sightly Include Statement Implicit Object

42
Adobe Experience Manager Developer Guide

Sightly Include Statement: Includes the rendering of the indicated template (Sightly, JSP,
ESP, etc.)

1 <section data-sly-include="path/to/template.html"></section>

Output:

1 <section><!-- Result of the rendered resource --></section>

Sightly Resource Statement Implicit Object

Sightly Resource Statement: Includes the result of the indicated resource

1 <article data-sly-resource="path/to/resource"></article>

Output:

1 <article><!-- Result of the rendered resource --></article>

COMPONENT DEVELOPMENT SIGHTLY VS JSP

As we have seen above using sightly component development becomes a part of web
developer instead of java developer. It reduces development time and cost for template
designing a lot as you can see in below diagram.

43
Adobe Experience Manager Developer Guide

WCMUsePojo code:

package com.kishore.sightly;

public class GetMap extends WCMUsePojo {

Map<String, String> myMap = null;

@Override

public void activate() throws Exception {

myMap = new HashMap<String, String>();

myMap.put("name", "Kishore");

public Map<String, String> getmyMap() {

return myMap;

HTL code:

<sly data-sly-use.model="com.kishore.sightly.GetMap" />

Name: ${model.myMap['name']}

SLING MODELS IN AEM

Many Sling projects want to be able to create model objects – POJOs which are
automatically mapped from Sling objects, typically resources, but also request objects.
Sometimes these POJOs need OSGi services as well.

44
Adobe Experience Manager Developer Guide

In simple terms Sling Models are simple POJO classes which are mapped automatically
with Sling Objects (resource, request objects..) and allow us to access jcr node property
values directly into java classes.

Advantages of using Sling Models

 Pure POJO classes.


 Entirely annotation driven(Need to write less code).
 Can adapt multiple objects – – minimal required Resource and
SlingHttpServletRequest
 OOTB, support resource properties (via ValueMap), SlingBindings, OSGi services,
request attributes
 Support both classes and interfaces.
 Plugabble.
 Work with existing Sling infrastructure (i.e. not require changes to other bundles).

SLING MODEL ANNOTATION

Creating an adaptable class by annotation

First step during creation of sling model is to adapt the POJO class to a Object type(
Resource, Request etc..)

1 // Traditional way of adapting to resource using java class

2 Resource r = getResource();

3 return r.adaptTo(customClassName.class);

5 // Creating adaptable resource class using sling annotation

45
Adobe Experience Manager Developer Guide

6 @Model(adaptables = Resource.class)

7 public class customClassName{

8 ...

9 }

Injecting properties in POJO class

Lets understand it with the help of below code:-

1 // Traditional way to getting values from jcr nodes in Java Class.

2 @Component

3 @Service

4 @Properties({

5 @Property(name = "adaptables", value = {"Resource" }),

6 @Property(name = "adapters", value = {"YourCustom" })

7 })

9 // Retrieving vales from jcr node through inject in Sling Model

10 @Model(adaptables = Resource.class)

46
Adobe Experience Manager Developer Guide

11 public class slingModelExample {

12 @Inject // email property is always looked from Resource( after adapting to


ValueMap), if this property value
13
is not present then it returns null. If this property is in itself not
14 available then it throws exception.

15 private String email;

16 @Inject @Optional // It is not mandatory to have firstname property in


Resource.
17

private String firstName;


18

// Use @Named if jcr node property name is different than class variable.
19

use @Default if you want to assign default values, If empty then assign
20 default value as 'NA'

21 @Inject @Named("surname") @Default(values="NA")

22 private String lastName;

23 }

24 @Inject // OSGi Service

25 private Externalizer externalizer;

26

47
Adobe Experience Manager Developer Guide

27 //@PostConstructor annotation defines that this method will run after


injecting all field
28
@PostConstruct
29
protected void init() {

// gets executed after the class is created and all variables are injected

Note: - We can also inject OSGI services.

So, just to summarize above code: -

 @Inject:- email property is always looked from Resource( after adapting to ValueMap),
if this property value is not present then it returns null. If this property is in itself not
available, then it throws exception.
 @Inject @Optional: - It is not mandatory to have firstname property in Resource.
 @Named: - Use it if jcr node property name is different than class variable.
 @Default :- use it if you want to assign default values, If empty then assign default
value as ‘NA’.
 @PostConstructor:- annotation defines that this method will run after injecting all
field.

USE SLING MODEL WITH SIGHTLY: -

In our last post, we have seen how to create aem multi module project. In this tutorial, i am
going to use the sling model and hello world component that is created by AEM Multi
Module project. You can create sling model in your existing project also. For doing this you
need to check two things.

48
Adobe Experience Manager Developer Guide

 Correct dependencies for sling model in your project pom.xml.

1 <dependency>

2 <groupId>org.apache.sling</groupId>

3 <artifactId>org.apache.sling.models.api</artifactId>

4 </dependency>

Note:- You can also verify dependencies from depfinder tool. Search
for org.apache.sling.models.annotations.Model dependency. If it is available then you
are good else add this dependency in pom.

49
Adobe Experience Manager Developer Guide

 Add your java package information in your maven-bundle plugin in pom.xml of


respective module.

What will happen if i don’t add these dependencies?

If you don’t add java packages to your pom.xml then maven won’t add these packages into
header entry of your bundle manifest file. Due to which these classes will not behave as
sling models and will work as simple java classes.

Note: - If you miss to add your sling model package in pom.xml then it won’t through any
error in error.log file.

CREATE SLING MODELS AND USE THEM ON COMPONENTS USING SIGHTLY

Let’s explore the sling model

 Go to Crxde.
 Go to hello world component (/apps/aemtutorials/components/content/helloworld).

50
Adobe Experience Manager Developer Guide

Below figure will show how we are passing the values from jcr node to sling model and
retrieving it in our hello world component script.

Now lets add one more field in model and retrieve its value in sightly. We have a text
property in dialog box lets add it also to sling model and get it from there to hello
world.html.

 Open eclipse go to HelloWorldModel.java.


 Create a new string variable by name text
 Add @Inject annotation on it.
 Add @Default annotation on it, in case it is empty.

51
Adobe Experience Manager Developer Guide

 Open helloWorld.html file


 Add below code to helloWorld.html file.

<pre data-sly-
1
use.refObject="org.training.aemcq5tutorials.core.models.HelloWorldModel">

2
${refObject.text}

3
</pre>

 Add ${refObject.text} to access text value from sling model.


Note:- While accessing a method we remove get from it and change the first
uppercase letter to small case.

 Build the code using command prompt.


 Open command prompt (cmd) and go to project pom.xml location.
 Run below command

52
Adobe Experience Manager Developer Guide

1 mvn clean install -P aemcq5tutorials-author

Testing Sightly Component

 Go to Site Admin.
 Create a page Home under english, by using aem content template.

53
Adobe Experience Manager Developer Guide

 Double click and open Home page.


 Drag and drop hello world component from sidekick to parsys.
 As we have not provided and value to text component it will print default text.

 Right click and edit helloworld component and add text “Welcome to Training” and
click OK.

54
Adobe Experience Manager Developer Guide

SCHEDULARS IN AEM (SCHEDULER SERVICE):

The scheduler is a service for scheduling other services/jobs (it uses the open source
Quartz library). The scheduler can be used in two ways, by registering the job through the scheduler API
and by leveraging the whiteboard pattern that is supported by the scheduler. In most cases the
whiteboard pattern is preferred.

Apache Sling Scheduler enables you to easily schedule jobs within your application.
Jobs can be executed at a specific time, regularly at a given period or at the time given by a cron
expression by leveraging the Sling scheduler service.

Scheduling in CQ uses the open source Quartz library, part Sling Commons:
‘org.apache.sling.commons.scheduler.Scheduler’. It is used to execute jobs at predefined
times either periodically or at a set time. It is based on the Quartz scheduling library and can
therefore make use of its syntax for defining the execution times of jobs, making it possible to
precisely indicate times.

The scheduler can be used in two ways,

 by registering the job through the scheduler API and


 by leveraging the whiteboard pattern that is supported by the scheduler.

The following examples show you how to define and schedule a job by leveraging the whiteboard pattern.

SCHEDULING WITH A CRON EXPRESSION :

 The cron expression format is described in the Quartz Cron Documentation and requires either 6 or 7 fields
separated by white space. The first field always indicates the second (not the minute).
 The following job is executed every minute by setting scheduler.expression to the cron expression 0 * * * *
?:

 package sling.docu.examples;

 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.felix.scr.annotations.Property;

55
Adobe Experience Manager Developer Guide

 @Component
 @Service(value = Runnable.class)
 @Property( name = "scheduler.expression", value = "0 * * * * ?")
 public class ScheduledCronJob implements Runnable {

 /** Default log. */
 protected final Logger log =
LoggerFactory.getLogger(this.getClass());

 public void run() {
 log.info("Executing a cron job (job#1) through the whiteboard
pattern");
 }
 //
 }

Scheduling at periodic times:

The following job is executed every ten seconds by setting scheduler.period to 10:

 package sling.docu.examples;

 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.felix.scr.annotations.Property;

 @Component
 @Service(value = Runnable.class)
 @Property( name = "scheduler.period", longValue = 10)
 public class ScheduledPeriodicJob implements Runnable {

 /** Default log. */
 protected final Logger log =
LoggerFactory.getLogger(this.getClass());

56
Adobe Experience Manager Developer Guide


 public void run() {
 log.info("Executing a perodic job (job#2) through the
whiteboard pattern");
 }
 //
 }

PREVENTING CONCURRENT EXECUTION

 By default, jobs can be concurrently executed. To prevent this, set the scheduler.concurrent property to
false:

 @Property(name="scheduler.concurrent", boolValue=false)

SCHEDULING THE JOB JUST ONCE IN A CLUSTER

 If the same code/same services is executed on multiple nodes within a cluster, the same job might be
scheduled on each instance. If this is not desired, the job can either be bound to the leader of the topology
or a single instance (which one this is, is not further defined):

@Property(name="scheduler.runOn", value="LEADER");

or

@Property(name="scheduler.runOn", value="SINGLE");

 Since in contrast to Sling Jobs the scheduler queue is only held in memory, there will be no distribution of
jobs. So if job '1' was scheduled on instance 'a' with the option to run on the leader only, but the leader is
instance 'b', which hasn't the job in the queue, the job will never be executed by any instance!

The Scheduler API

 The scheduler has methods to execute jobs periodically, based on a cron expression or at a given time. For
more details please refer to the javadocs.

SCHEDULED JOBS REGISTERED THROUGH THE SCHEDULER API :

 The following examples show you how to define and schedule a job that is registered through the scheduler
api.

57
Adobe Experience Manager Developer Guide

DEFINING THE JOB

The following code sample defines a job object that writes a message in the logs:

 final Runnable job = new Runnable() {


 public void run() {
 log.info("Executing the job");
 }
 };

SCHEDULING WITH A CRON EXPRESSION

 To execute the job as defined above at 10:15am every Monday, Tuesday, Wednesday, Thursday and
Friday, you can use the addJob() method with the following parameters:

 String schedulingExpression = "0 15 10 ? * MON-FRI";


 this.scheduler.addJob("myJob", job, null, schedulingExpression, true);

 Refer to http://www.docjar.com/docs/api/org/quartz/CronTrigger.html to define more scheduling


expressions.

SCHEDULING AT PERIODIC TIMES

 To execute the job as defined above every 3 minutes (180 seconds), you can use the addPeriodicJob()
method with the following parameters:

 long period = 3*60; //the period is expressed in seconds


 this.scheduler.addPeriodicJob("myJob", job, null, period, true);

SCHEDULING AT A GIVEN TIME

 To execute the job as defined above at a specific date (on January 10th 2020), you can use the fireJobAt()
method with the following parameters:

 SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");


 String date = "2020/01/10";
 java.util.Date fireDate = formatter.parse(date);
 this.scheduler.fireJobAt("myJob", job, null, fireDate);

58
Adobe Experience Manager Developer Guide

A SERVICE SCHEDULING THE JOB BASED ON 3 DIFFERENT KINDS OF SCHEDULING

 The code implementing a service that simultaneously executes the job based on 3 different kinds of
scheduling can look as follows:

 package sling.docu.examples;

 import java.io.Serializable;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;

 import org.apache.sling.commons.scheduler.Scheduler;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;

 /**
 * This service executes scheduled jobs
 *
 */
 @Component
 public class HelloWorldScheduledService {

 /** Default log. */
 protected final Logger log =
LoggerFactory.getLogger(this.getClass());

 /** The scheduler for rescheduling jobs. */
 @Reference
 private Scheduler scheduler;

59
Adobe Experience Manager Developer Guide

 protected void activate(ComponentContext componentContext) throws


Exception {
 //case 1: with addJob() method: executes the job every minute
 String schedulingExpression = "0 * * * * ?";
 String jobName1 = "case1";
 Map<String, Serializable> config1 = new HashMap<String,
Serializable>();
 boolean canRunConcurrently = true;
 final Runnable job1 = new Runnable() {
 public void run() {
 log.info("Executing job1");
 }
 };
 try {
 this.scheduler.addJob(jobName1, job1, config1,
schedulingExpression, canRunConcurrently);
 } catch (Exception e) {
 job1.run();
 }

 //case 2: with addPeriodicJob(): executes the job every 3
minutes
 String jobName2 = "case2";
 long period = 180;
 Map<String, Serializable> config2 = new HashMap<String,
Serializable>();
 final Runnable job2 = new Runnable() {
 public void run() {
 log.info("Executing job2");
 }
 };
 try {
 this.scheduler.addPeriodicJob(jobName2, job2, config2,
period, canRunConcurrently);
 } catch (Exception e) {
 job2.run();

60
Adobe Experience Manager Developer Guide

 }

 //case 3: with fireJobAt(): executes the job at a specific date
(date of deployment + delay of 30 seconds)
 String jobName3 = "case3";
 final long delay = 30*1000;
 final Date fireDate = new Date();
 fireDate.setTime(System.currentTimeMillis() + delay);
 Map<String, Serializable> config3 = new HashMap<String,
Serializable>();
 final Runnable job3 = new Runnable() {
 public void run() {
 log.info("Executing job3 at date: {} with a delay of:
{} seconds", fireDate, delay/1000);
 }
 };
 try {
 this.scheduler.fireJobAt(jobName3, job3, config3,
fireDate);
 } catch (Exception e) {
 job3.run();
 }
 }

 protected void deactivate(ComponentContext componentContext) {
 log.info("Deactivated, goodbye!");
 }

 }

SLING SERVLETS IN AEM:

SLING SERVLET USING PATH

61
Adobe Experience Manager Developer Guide

Lets write a sling servlet that returns json data by registering using path. When you create a
project using AEM plugin, it will create a sample servlet file for you under core–> servlet

 Open SimpleServlet.java file and paste below code, i will explain the code line by line.

1 /*

2 * Copyright 2015 Adobe Systems Incorporated

3 *

4 * Licensed under the Apache License, Version 2.0 (the "License");

5 * you may not use this file except in compliance with the License.

6 * You may obtain a copy of the License at

7 *

8 * http://www.apache.org/licenses/LICENSE-2.0

9 *

10 * Unless required by applicable law or agreed to in writing, software

11 * distributed under the License is distributed on an "AS IS" BASIS,

12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

13 * See the License for the specific language governing permissions and

62
Adobe Experience Manager Developer Guide

14 * limitations under the License.

15 */

16 package org.training.aemcq5tutorials.core.servlets;

17

18 import org.apache.felix.scr.annotations.Reference;

19 import org.apache.felix.scr.annotations.sling.SlingServlet;

20 import org.apache.sling.api.SlingHttpServletRequest;

21 import org.apache.sling.api.SlingHttpServletResponse;

22 import org.apache.sling.api.resource.Resource;

23 import org.apache.sling.api.servlets.SlingAllMethodsServlet;

24 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;

25 import org.apache.sling.commons.json.JSONException;

26 import org.apache.sling.commons.json.JSONObject;

27

28 import javax.jcr.Repository;

29 import javax.servlet.ServletException;

63
Adobe Experience Manager Developer Guide

30 import java.io.IOException;

31

32 /**

33 * Servlet that writes some sample content into the response. It is mounted
for
34
* all resources of a specific Sling resource type. The
35
* {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
36
* idempotent. For write operations use the {@link SlingAllMethodsServlet}.
37
*/
38
@SuppressWarnings("serial")
39
@SlingServlet(paths = "/bin/custom/path")
40
public class SimpleServlet extends SlingSafeMethodsServlet {
41
@Reference
42
private Repository repository;
43
@Override
44
protected void doGet(final SlingHttpServletRequest req,
45

64
Adobe Experience Manager Developer Guide

46 final SlingHttpServletResponse resp) throws ServletException,


IOException {
47
resp.setContentType("application/json");
48
String keys[] = repository.getDescriptorKeys();
49
JSONObject jsonobject = new JSONObject();
50
for(int i=0;i<keys.length;i++){
51
try {
52
jsonobject.put(keys[i], repository.getDescriptor(keys[i]));
53
} catch (JSONException e) {
54
// TODO Auto-generated catch block
55
e.printStackTrace();
56
}
57
}
58
resp.getWriter().println(jsonobject.toString());
59

60
}

65
Adobe Experience Manager Developer Guide

 Here i am registering our simple servlet at path /bin/custom/path.


 Then i am setting the content type as json.
 Finally i am returning the response.

AJAX CALL THAT YOU C AN USE TO CALL THIS SERVLET USING R EST API:

$.ajax({
1

type : "POST",
2

url : '/bin/custom/path',
3

/*data : {
4

pass your request parameter here, currently we are not passing any
5
data

6
},*/

7
success : function(data, textStatus, jqXHR) {

8
//write your logic that you need to perform on sucess

9
},

10
error : function(XMLHttpRequest, textStatus, errorThrown) {

11
//write your logic that you need to perform on error

12
}

66
Adobe Experience Manager Developer Guide

13 });

Now go to your browser type http://localhost:4502/bin/custom/path and you can see you
json, This url can be used by front end developers to get the json response and process it
accordingly.

SLING SERVLET USING A RESOURCE TYPE AND SELECTOR

Lets write a sling servlet that returns json data by registering using resource type and
selector.

 Again Open SimpleServlet.java file and paste below code, i will explain the code line by
line.

1 /*

2 * Copyright 2015 Adobe Systems Incorporated

3 *

4 * Licensed under the Apache License, Version 2.0 (the "License");

5 * you may not use this file except in compliance with the License.

67
Adobe Experience Manager Developer Guide

6 * You may obtain a copy of the License at

7 *

8 *

9 * Unless required by applicable law or agreed to in writing, software

10 * distributed under the License is distributed on an "AS IS" BASIS,

11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

12 * See the License for the specific language governing permissions and

13 * limitations under the License.

14 */

15 package org.training.aemcq5tutorials.core.servlets;

16

17 import org.apache.felix.scr.annotations.Reference;

18 import org.apache.felix.scr.annotations.sling.SlingServlet;

19 import org.apache.sling.api.SlingHttpServletRequest;

20 import org.apache.sling.api.SlingHttpServletResponse;

21 import org.apache.sling.api.resource.Resource;

68
Adobe Experience Manager Developer Guide

22 import org.apache.sling.api.servlets.SlingAllMethodsServlet;

23 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;

24 import org.apache.sling.commons.json.JSONException;

25 import org.apache.sling.commons.json.JSONObject;

26

27 import javax.jcr.Repository;

28 import javax.servlet.ServletException;

29 import java.io.IOException;

30

31 /**

32 * Servlet that writes some sample content into the response. It is mounted
for
33
* all resources of a specific Sling resource type. The
34
* {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
35
* idempotent. For write operations use the {@link SlingAllMethodsServlet}.
36
*/
37

69
Adobe Experience Manager Developer Guide

38 @SuppressWarnings("serial")

39 @SlingServlet(resourceTypes = "geometrixx/components/homepage",

40 selectors = "data",

41 extensions = "html",

42 methods = "GET",

43 metatype =true)

44 public class SimpleServlet extends SlingSafeMethodsServlet {

45 @Reference

46 private Repository repository;

47 @Override

48 protected void doGet(final SlingHttpServletRequest req,

49 final SlingHttpServletResponse resp) throws ServletException,


IOException {
50
resp.setContentType("application/json");
51
String keys[] = repository.getDescriptorKeys();
52
JSONObject jsonobject = new JSONObject();
53

70
Adobe Experience Manager Developer Guide

54 for(int i=0;i<keys.length;i++){

55 try {

56 jsonobject.put(keys[i], repository.getDescriptor(keys[i]));

57 } catch (JSONException e) {

58 // TODO Auto-generated catch block

59 e.printStackTrace();

60 }

61 }

62 resp.getWriter().println(jsonobject.toString());

63

64 }

 Here i am registering our simple servlet at resourceType


geometrixx/components/homepage and selector data.

71
Adobe Experience Manager Developer Guide

AJAX CALL THAT YOU C AN USE TO CALL THIS SERVLET USING R EST API:

$.ajax({
1

type : "POST",
2

url : '/content/geometrixx/en.data.html,
3

/*data : {
4

pass your request parameter here, currently we are not passing any
5
data

6
},*/

7
success : function(data, textStatus, jqXHR) {

8
//write your logic that you need to perform on sucess

9
},

72
Adobe Experience Manager Developer Guide

10 error : function(XMLHttpRequest, textStatus, errorThrown) {

11 //write your logic that you need to perform on error

12 }

13 });

Now go to your browser type http://localhost:4502/content/geometrixx/en.data.html and


you can see you json, This url can be used by front end developers to get the json response
and process it accordingly.

ADVANTAGES OF REGISTERING SERVLET USING SELECTOR OVER PATH:

Adobe recommends using resourceType instead of using path because of following


reasons:-

 When we register a servlet using path , we must be specific what all paths are allowed
as If we define something randomly, our servlet might not be function properly. Only a
limited set of paths are allowed and the rest are blocked. We can add more path using
Apache Sling Servlet / Script Resolver and Error Handler. Allowing more paths to
execute servlet make you application vulnerable. That’s why you should not open more
doors for servlets to run until and unless it is required.

73
Adobe Experience Manager Developer Guide

 You might also need to tell specific paths to your consumers , who are consuming
servlet response using ajax and any change in that path could have a serious affect.
This might not be the case when you use resourceType.
 Sling Engine will take care of permissions if you register servlet using Resource Type.
Users who cannot access a particular resource will not be able to invoke the servlet.

SLING SERVLET BEST PRACTICES:

DO’S

1 @SlingServlet(

2 resourceTypes = "sling/servlet/default",

3 selectors = "selector",

4 extensions = "tab",

5 methods = HttpConstants.METHOD_GET

6 )

74
Adobe Experience Manager Developer Guide

DONT

@Component

1
@Service(value = javax.servlet.Servlet.class)

2
@Properties({ @Property(name = "sling.servlet.resourceTypes", value = {

3 "sling/servlet/default" }),

4 @Property(name = "sling.servlet.selectors", value = { "selector" }),

5 @Property(name = "sling.servlet.extensions", value = { "tab" }),

6 @Property(name = "sling.servlet.methods", value = { HttpConstants.METHOD_GET


}) })

DO’S

1 @SlingServlet(

2 resourceTypes = "sling/servlet/default", selectors = "selector",

3 extensions = "tab", methods = HttpConstants.METHOD_GET

4 )

5 @Properties({

6 @Property(name = Constants.SERVICE_VENDOR, value = "Cognifide"),

75
Adobe Experience Manager Developer Guide

7 @Property(name = Constants.SERVICE_DESCRIPTION, value = "Some description")

8 })

DONT

@SlingServlet(methods = "GET")
1

@Properties({
2

@Property(name = Constants.SERVICE_VENDOR, value = "Cognifide"),


3

@Property(name = Constants.SERVICE_DESCRIPTION, value = "Some description"),


4

@Property(name = "sling.servlet.selectors", value = "selector"),


5

@Property(name = "sling.servlet.extensions", value = "tab"),


6

@Property(name = "sling.servlet.resourceTypes", value = {


7
"sling/servlet/default" })

8
})

DO’S

76
Adobe Experience Manager Developer Guide

1 @SlingServlet(

2 resourceTypes = "sling/servlet/default", selectors = "selector",

3 extensions = "tab", methods = HttpConstants.METHOD_GET

4 )

DONT

1 @Service

2 @Component

3 @SlingServlet(

4 resourceTypes = "sling/servlet/default", selectors = "selector",

5 extensions = "tab", methods = HttpConstants.METHOD_GET

6 )

77
Adobe Experience Manager Developer Guide

OSGI SERVICES IN AEM:

An OSGi service is a java object instance, registered into an OSGi framework with a set of properties. Any java
object can be registered as a service, but typically it implements a well-known interface.

The OSGi R3 specification, chapter 4.10 is highly recommended reading. Also, the javadoc for BundleContext
contains lot of information.

The client of a service is always an OSGi bundle, i.e. a piece of java code possible to start via the
BundleActivator interface.

Each bundle may register zero or more services. Each bundle may also use zero or more services. There exists
no limit on the number of services, more than the ones given by memory limits or java security permissions.

Both publishing/registering and usage of services can be restricted by using java security permissions.

Registering a very simple object as a service

Long i = new Long(20);


Hashtable props = new Hashtable();
props.put("description", "This an long value");
bc.registerService(Long.class.getName(), i, props);

Note: a service can also be registered as several interfaces. In this case, the object must implement all of the
interfaces.

WHAT IS A SERVICE FACTORY?

An OSGi service factory is a special class ServiceFactory, which can create individual instances of service
objects for different bundles.

Sometimes a service needs to be differently configured depending on which bundle uses the service. For
example, the log service needs to be able to print the logging bundle's id, otherwise the log would be hard to
read.

A service factory is registered in exactly the same way as a normal service, using register Service, the only
difference is an indirection step before the actual service object is handed out.

The client using the service need not, and should not, care if a service is generated by a factory or by a plain
object.

A simple service factory example

class LongFactory implements ServiceFactory {


public Object getService(Bundle bundle, ServiceRegistration reg) {
// each bundle gets a Long with it's own id
return new Long(bundle.getBundleId());
}

78
Adobe Experience Manager Developer Guide

void ungetService(Bundle bundle, ServiceRegistration reg, Object service)


{
// nothing needed in this case
}
}

ServiceFactory factory = new LongFactory();


bc.registerService(Long.class.getName(), factory, new Hashtable());

Note: The framework will cache generated service objects. Thus, at most one service can be generated per
client bundle.

WHAT CAN SERVICES BE USED FOR?

The service concept is a very general-purpose tool, but some examples are:

 Export functionality from a bundle to other bundles


 Import functionality from other bundles
 Register listeners for events from other bundles
 Expose external devices, such as UPnP devices or even hardware, to other OSGi bundles. See the
Device and UPnP APIs
 Expose java code running in OSGI to an external network, e.g. via the UPnP or SOAP protocols.
 Bundle configuration, using the Configuration Manager

Generally, services is the preferred method bundles should use to communicate between each other.

HOW ARE SERVICES ACCESSED?

Services are always accessed via Service References, which uniquely points to a service object.

To access a service, the following procedure must always be used (possibly wrapped by utility code):

1. Get a ServiceReference
2. Get the service object from the reference, using BundleContext.getService()

ServiceReference are typically retreived by:

1. Explicit usage of BundleContext.getService()


This returns either the highest ranked service of the given class, or null
2. Explicit usage of BundleContext.getServices()
This return the complete set of matching services, or null
3. Callback from a ServiceListener
4. Using the utility class ServiceTracker

All cases, except the first, allow the client to specify a set of properties that the service must fullfill. These
properties are specified using LDAP filters. Zero or more service references can match a given filter.

79
Adobe Experience Manager Developer Guide

A typical filter contains a class name and a set of properties. The example below matches a Http service having
a "port" property equal to 80.

An LDAP filter string

(&(objectclass=org.osgi.service.http.HttpService)(port=80))

As soon as a ServiceReference is available, the service object can be accessed using a cast:

HttpService http = (HttpService)bc.getService(sr);

After this, the service object can be accessed as any other java object. Actually, it is a fully normal java object,
more exact, it is the same object as the bundle registering the service created.

RELEASING SERVICES

As soon as the service isn't needed anymore, the client should release the service by calling the
BundleContext.ungetService() method.

bc.ungetService(sr);

All services are automatically released when the client bundles stops. No special service cleanup is needed in
BundleActivator.stop().

Note that service should only be released when really unused. Some services may keep a state for each using
bundle, and releasing the service will release this state, which may, or may not, be the intention. Each service
documentation must be consulted. An example of this is the HttpService, which will remove all servlets and
resources from itself when a client releases the HttpService.

Some special words are needed when using service listeners. A listener will get a
ServiceEvent.UNREGISTERING event when a service is in the process of being unregistering from the
framework.

While in this UNREGISTERING listener, the getService() call should not be expected to return a valid
service object. In fact, the expected value is null, even if the spec is a bit vague on this. The OSGi reference
implementation does however return null in this case.

Note: It's fully possible for a client to hold on to a service object via a variable, even after the exporting
bundle has been stopped. The client shouldn't expect the service to work in this case and this also blocks any
garbage collection. Thus, don't forget to null variables holding services when the service is released.

BEST PRACTICES FOR ACCESSING OSGI SERVICES

OSGi services must always be considered volatile, and may disappear or become unusable at any time.

Suggested practices:

80
Adobe Experience Manager Developer Guide

 Always expect RuntimeException when calling a service


A service may fail at any time, similar to RMI based code. The recommended exception an unsuable
service should throw is IllegalStateException This does not mean that a try/catch block
should be made on each service call, rather that the code must be prepared to handle such exceptions
on a higher level.
 Use the white-board model
If possible, construct your code so users of your bundle functionality can participate by registering
services, instead of getting services. It's much easier to register a service, than to get it. Thus, if you
want to make life easier for clients, go for the white-board model.
 Use listeners
ServiceListener and ServiceTracker provide various levels of automation for getting services.
 Use the declarative ServiceBinder
The ServiceBinder by Cervantes/Hall provide a framework for cases where it's possible to declare
service dependecies in XML.

Consider the bad-styled, but common, code:


Bad code example

01: ServiceReference sr =
bc.getServiceReference(HttpService.class.getName());
02: HttpService http = (HttpService)bc.getService(sr);
03: http.registerServlet(....)
Three things can fail, one for each line!

1. The ServiceReference can be null if no HttpService is registered, resulting in


NullPointerException on line 2.
2. The http service object cannot be get, due to missing permissions, possible timing issues if the http
unregisters between lines 1 and 2, causing NullPointerException on line 3.
3. The http service may have become unusable, resulting in any RuntimeException subclass, most
likely IllegalStateException on line 3.

Additionally, the code above does not handle the case where more than one service is registered and actions
should be taken on each of them.

The NPE problems can be naively avoided by adding conditionals:

01: ServiceReference sr =
bc.getServiceReference(HttpService.class.getName());
02: if(sr != null) {
03: HttpService http = (HttpService)bc.getService(sr);
04: if(http != null) {
05: http.registerServlet(....)
06: }
07: }

This approach quickly becomes very cumbersome, and also creates an undesirable start order problem, since
the HttpService must be available when the code is run.

By using a service listener, the code can avoid the first ServiceReference null problem:

81
Adobe Experience Manager Developer Guide

Using a service listener

01: ServiceListener sl = new ServiceListener() {


02: public void ServiceChanged(ServiceEvent ev) {
03: ServiceReference sr = ev.getServiceReference();
04: switch(ev.getType()) {
05: case ServiceEvent.REGISTERED:
06: {
07: HttpService http = (HttpService)bc.getService(sr);
08: http.registerServlet(...);
09: }
10: break;
11: default:
12: break;
13: }
14: }
15: };
16:
17: String filter = "(objectclass=" + HttpService.class.getName() + ")";
18: try {
19: bc.addServiceListener(sl, filter);
20: } catch (InvalidSyntaxException e) {
21: e.printStackTrace();
22: }

The possible Runtime Exception when actually calling the service (line 8) is handled by the framework event
delivery code, so if no special handling is needed in the client code, nothing needs to be done.

There's still one problem -- if all HttpServices already had been registered, the listener above would not be
called until the HttpServices were restarted. A small trick solves this: Manually construct REGISTERED Service
Events and call the listener:

Construct ServiceEvents - contd. from above

18: try {
19: bc.addServiceListener(sl, filter);
20: ServiceReference[] srl = bc.getServiceReferences(null, filter);
21: for(int i = 0; srl != null && i < srl.length; i++) {
22: sl.serviceChanged(new ServiceEvent(ServiceEvent.REGISTRED,
23: srl[i]));
24: }
25: } catch (InvalidSyntaxException e) {
26: e.printStackTrace();
27: }

Now the number of lines has grown from three to 25+. Which may be OK if this is a one-time operation. But if
continuous use of a service is intended, it's easier to use a ServiceTracker:

ServiceTracker example

01: ServiceTracker logTracker = new ServiceTracker(bc,


LogService.class.getName(), null);
02: logTracker.open();

82
Adobe Experience Manager Developer Guide

03: ((LogService)logTracker.getService()).doLog(...);

The tracker guarantees to hold all currently available services, but may naturally return null if no services are
available. This is often OK, since the code need to be prepared for RuntimeException anyway.

The down-side of this approach is the continuous and annoying usage of casting to get the desired object.
Wrapping this in a single utility method can ease usage a bit:

01: ServiceTracker logTracker;


02:
03: void init() {
04: logTracker = new ServiceTracker(bc, LogService.class.getName(), null);
05: }
06:
07: LogService getLog() {
08: return (LogService)logTracker.getService();
09: }
10:
11: void test() {
12: getLog().doLog(...);
13: }

THE WHITE-BOARD MODEL

"Don't call getService(), call registerService() instead!"

Consider the HttpService case. All clients must constantly monitor the framework in some way to add its
servlet(s) to the web server. This requires at least the amount of code examplified above, and even this
doesn't completely guard against timing problems.

Additionally, the Http service must provide special methods for adding and removing servlets, and maintain an
internal list of added servlets. This adds complexity both to the API and to the internal server code.

This is a very common scenario -- some kind of callbacks/listeners are needed and the server needs to keep
track of all available listeners.

The OSGi framework already provides exactly this functionality.

Thus, an alternative and better approach is to let the client register its servlets into the framework, and
let the http server use this list instead.

Servlet client

01: class MyServlet extends HttpServlet {


02: ...
03: }
04:
05: HttpServlet servlet = new MyServlet();
06: Hashtable props = new Hashtable();
07: props.put("alias", "/servlets/foo"); // desired http alias

83
Adobe Experience Manager Developer Guide

08: ServiceRegistration reg =


09: bc.registerService(HttpServlet.class.getName(), servlet, props);

The client needn't do anything more. If the servlet should be removed, it is simply unregistered from the
framework.

10: reg.unregister();

The new, improved http server would monitor the framework for all services being HttpServlets, and use the
"alias" property to set the alias.

Below is a minimalistic wrapper for the existing http service: (a complete class doing this can be found in the
Http Console example code.

HttpService wrapper

void open() {
httpTracker = new ServiceTracker(bc, HttpService.class.getName(), null);
httpTracker.open();

ServiceListener sl = new ServiceListener() {


public void serviceChanged(ServiceEvent ev) {
ServiceReference sr = ev.getServiceReference();
switch(ev.getType()) {
case ServiceEvent.REGISTERED:
{
registerServlet(sr);
}
break;
case ServiceEvent.UNREGISTERING:
{
unregisterServlet(sr);
}
break;
}
}
};

String filter = "(objectclass=" + HttpServlet.class.getName() + ")";


try {
bc.addServiceListener(sl, filter);
ServiceReference[] srl = bc.getServiceReferences(null, filter);
for(int i = 0; srl != null && i < srl.length; i++) {
sl.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED,
srl[i]));
}
} catch (InvalidSyntaxException e) {
e.printStackTrace();
}
}

void registerServlet(ServiceReference sr) {


HttpServlet servlet = (HttpServlet)bc.getService(sr);

84
Adobe Experience Manager Developer Guide

String alias = (String)sr.getProperty("alias");

Object[] httplist = httpTracker.getServices();

for(int i = 0; httplist != null && i < httplist.length; i++) {


HttpService http = (HttpService)httplist[i];
try {
Hashtable props = new Hashtable();
http.registerServlet(alias, servlet, props, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}

void unregisterServlet(ServiceReference sr) {


String alias = (String)sr.getProperty("alias");

Object[] httplist = httpTracker.getServices();

for(int i = 0; httplist != null && i < httplist.length; i++) {


HttpService http = (HttpService)httplist[i];
try {
http.unregister(alias);
} catch (Exception e) {
e.printStackTrace();
}
bc.ungetService(sr);
}
}

85
Adobe Experience Manager Developer Guide

WORKFLOWS IN AEM

Workflow is a well-defined series of steps that allows to automate activities of Experience Manager. It is
divided into various steps including people (participants), procedures (process) or some tools. The flow of
workflow can be either sequential or parallel when multiple procedures can run parallely to each other. In
short, a workflow is similar to a flow-chart which describes the series of procedures to be executed having
multiple participants to achieve a desired outcome.

There are many out of the box workflow models available for use and we can write our custom workflows
which can be tailored as per the business needs of the company.

There can be plethora of use cases for writing workflows that may depend on the business needs.

For example, the process of publishing a page can be customized and tailored for inclusion of some special
participants that need to approve the request for activation or send a mail after approval or rejection.

WORKFLOW MODELS

Workflow Model is a container or blueprint of the workflow that combines the workflow steps and link them
logically.

 It has a start and an end node (plus an optional participant step) by default.
 It can contain different nodes and the transitions that link them. The workflow nodes can get any input from
author or can do processing via Java code or ECMA scripts.
 Workflow payload is an important term which is considered as a resource on which workflow will perform
its functions.
List of workflows can be seen on http://localhost:4502/libs/cq/workflow/content/console.html.

86
Adobe Experience Manager Developer Guide

Figure 1: AEM Workflow Console

Figure 2: Tabs in Workflow Console


These are the tabs that contain the information about the workflows.
 Models:- has workflow models having title of the workflow, version, description, and model id.
 Instances:- lists the active instances of workflows having status (running, suspended etc.), initiator, start
time, workflow model, payload associated with the workflow.
 Archive:- contains the history of all the workflow instances. It contains the status (completed, aborted
etc.), initiator, start and end time, workflow model, payload, workflow title etc.
 Launcher:- contains the launchers of workflow models that trigger initiation of workflows automatically on
some action. It contains fields such as event type (created, deleted, modified), nodetype, globbing or path
specified for action of node, condition, workflow model that needs to be triggered, description, value of enabled,
exclusion list, run modes.
 Failure:- shows failed instances of workflow on which some error occurred during execution. The issues
can be fixed and workflow instances can be resumed.
Example
Let’s have a look at one of the practical examples of workflow. To create a new workflow we can add the title and
the name (cannot contain spaces) of the workflow by clicking on New tab.

87
Adobe Experience Manager Developer Guide

Figure 3: Create a new Workflow Model

Thereafter, we can edit the workflow created to customize it. This is the by default view of the workflow wherein
there is a start and an end node with a default participant step.

Figure 4: By default view of workflow


We can view the logical layout of the workflow in the console whereas to see the node structure stored for the
workflow we can see /etc/workflow/models/sample_workflow.

88
Adobe Experience Manager Developer Guide

Figure 5: Node structure of workflow in CRX


It contains metadata about the workflow stored in JCR. We can notice flow and model nodes. It has the nodes
between start and end node present in the workflow. The model node has all the steps added in the workflow marked
as nodes along with the transitions they have between them. We can see the metadata of node 6 in the snapshot since
it is a process step having title as Publish Page.
We can see the running instance of the workflow under /etc/workflow/instance path in CRX.

Figure 6: Nodes in trigger workflow instance


This is an example of trigger workflow having data (metadata and payload of which workflow instance is working
upon), history, metadata of a particular step and work Items associated with the workflow.

WORKFLOW NODES
There are many workflow nodes that can be dragged and dropped such as Participant step, process step, and split, or
split, dialog participant step, form participant step, container step, go to step etc.
1. PARTICIPANT STEP: In this step the user can give
 Title and description and select a user or a group.
 The email option will send an email in the inbox of the user/group.

89
Adobe Experience Manager Developer Guide

Figure 7: Participant Step


2. PROCESS STEP: In this step
 Common tab can contain title and description of the process step.
 There are timeout settings too in which we can set the timeout limit of the workflow after which the
timeout handler will start its execution.
 In the process tab we select the process from the dropdown (We can add our own process in the list using
java).
 We have to check the option of Handler Advance so as to allow the workflow process step to proceed to the
next step after performing its task.
 There is another field named as Arguments in which we can pass the arguments to the process step for
function and task.

Figure 8: Process Step

90
Adobe Experience Manager Developer Guide

Now, to add our own process in the list we have to make a workflow process and register it as a service in java and
can add the logical code that will execute on this process step

@Component(immediate = true, enabled= true, metatype = true)

@Service(WorkflowProcess.class)

@Property(name = "process.label", value = "Create Page Service", propertyPrivate = true)

public class TriggerWorkflow implements WorkflowProcess {

@Override

public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args) throws WorkflowException
{
}
This code snippet shows the basic skeleton of a workflow process that it required for process step.
@Component will register our Java class as a component with the properties that enables it immediately and helps
it get the metadata provided by the execute method of WorkflowProcess class.

@Service will register our Java class as a service to be used in the Workflow process.

@Properties will add certain properties such as process.label which will show our class in the process list of the
process step. The value of this property will be shown in the drop down list.

The Java class should implement WorkflowProcess interface and give definition to execute method. This method
provides three arguments namely WorkItem, WorkflowSession, MetaDataMap.

 WorkItem defines the currently started java process. It contains the data of the workflow and can be fetched
using this argument such as Id, workflow, workflow data etc. We can access the workflow object using this. We
can get payload of the data using a method of workItem.

String payload = workItem.getWorkflowData().getPayload().toString();

 WorkflowSession controls the workflow by providing methods that can deploy, complete, create, start,
stop, resume, suspend, retrieve, complete workflow models, instances or user/groups. We can start another
workflow using workflow session of current workflow.
 MetadataMap is a Map<String, Object> of properties that are entered in the dialog of the process step. We
can fetch the list of the arguments from metadata map.
There can be many other types of steps that can be configured within the workflow and can be tailored using java
code, scripts, parameters etc. to provide the desired functionality.

91
Adobe Experience Manager Developer Guide

3. An OR SPLIT can be used to introduce branching in the workflow with which only one branch of the
workflow can be activated (conditional) based on the script which is mentioned in the dialog.

 The user can give either the path of the script or can write ECMA script in the given tab.
 The Common tab has an option to select the number of branches required in the OR Split.

Figure 9: OR Split (marked with green)

92
Adobe Experience Manager Developer Guide

Figure 10: ECMA script written for branch 1 (set as default route).
We can write different condition for branch 2 or can upload a script.

4. AND SPLIT wherein all the branches go parallely and we can execute tasks for multiple processing.
5. A CONTAINER STEP can allow another workflow to be executed as a child of the current workflow.
This workflow is a sub workflow that can be instantiated. Another way of performing the same action is via
Java code where we can start a workflow using workflowSession.

WorkflowModel workflowModel = workflowSession.getModel("/etc/workflow/models/childworkflow/jcr:content/model");

WorkflowData workflowData = workflowSession.newWorkflowData("JCR_PATH", "/content/bhf/poc/sampleWorkflowPage");

workflowSession.startWorkflow(workflowModel, workflowData);

This code snippet gets the model of the child workflow that needs to be invoked. Thereafter, the data of the
workflow is created which is used to start the workflow in the current session.
6. GOTO STEP traverses between the steps in the workflow based on the result of the ECMA script. It can be
used to implement the use case of looping in the workflow process.
7. DIALOG PARTICIPANT STEP is a special scenario of participant step where the user/group needs to give
some information that is to be used in the workflow.
1. The additional step in this step is to provide a path of the dialog. We have to make that dialog in
CRX (/etc/workflows/dialog) and provide the path of that dialog to receive the input from the selected
user/group.
2. The structure of the dialog should be cq:dialog type. This data can be stored in the form of payload
(when we set the value of the property as ./jcr:content/nodename) which can be overwritten in
subsequent uses of this dialog.
3. The data can also be stored with the work item (when the value is node name) metadata and is
persisted with subsequent use of dialog.

WORKFLOW LAUNCHERS:

Workflow launchers can be used to trigger the workflow based on some event that can be specified in the
launcher. We can add a launcher under the Launcher tab.

93
Adobe Experience Manager Developer Guide

Figure 11: Creation of Launcher for Workflow


 Event type:- can be either created, modified or deleted i.e. the action on which the launcher will
trigger the workflow mentioned.
 Nodetype:- is for the type of the node on which the launcher will apply to start the workflow.
 Path:- specifies the path on which this action will be applied to during the workflow initiation i.e.
on the which the launcher of the workflow will be applied to.
 Condition tab:- determines the condition to be applied when the workflow is launched. This is
optional in case a user wants to start the launcher based on a specific condition only.
 Workflow:- Launcher needs to be associated with a workflow model so that it can be determined
that what will be triggered with the help of this launcher.
 Description:- can be set and activate should be enabled to enable the launch of the workflow
launcher.
 Exclude:- list is a comma separated list of JCR events or items to be ignored via workflow
triggering.
 Run modes:- in this dialog is to specify the server on which this will be applied to (author,
publish, author & publish).

94
Adobe Experience Manager Developer Guide

CONTENT FRAGMENTS IN AEM

Have you ever wondered how to easily create text snippets in Adobe Experience
Manager (AEM) and store them in the AEM repository, for easy re-use when authoring
web pages, mobile applications, social content, and so on?

In AEM 6.2, you can use content fragments that let you create original content in AEM,
enabling copy writers to create editorial content before it is being authored in a page,
and to further allow curating such content by creating channel specific variations and by
associating collections with relevant media content. As a result, web producers receive
content that is prepared and "ready to go”, enabling them to focus on assembling
content across channels, globally and on a local level.

Overview of AEM Content Fragments

It is important when using Content Fragments is to understand core concepts and


terminology.

95
Adobe Experience Manager Developer Guide

Content Fragments

Content Fragments are based on templates; not page templates, but specific fragment
templates.
Fragment templates are created and maintained in the AEM repository by using CRXDE
Lite. Typically, copy writers and authors select a template when creating a content
fragment.

Here is what templates define for a Content Fragment:

Elements

 Self-contained pieces of editorial content that are meant to be authored in a page with
their own design and layout, i.e. component, as opposed to "paragraphs" which are
meant to be authored with a common component.

Default content

 Content every user sees the first time a fragment is created.

96
Adobe Experience Manager Developer Guide

Fragments themselves have a name/title value, like every AEM asset, and contain the
following structural elements:

Paragraphs

 Groups of words separated by a vertical space (carriage return).


 Can include a title, which has to be forma ed as such (header). Otherwise titles are
seen as
paragraphs on their own.
 Paragraphs are important as fragment components allow creating fragment instances in
a page
with just one paragraph or a sequence of paragraphs. We will see this later on when
using a Content Fragment in a web page.

Variations

 Copies of the content master that are optimized for a certain editorial purpose or
channel. A mobile variation can for example be optimized for a mobile channel, by
removing and/or rewriting certain parts of a master. Or an email variation can be
optimized for using the same content in emails.

Associated Collections

 Relevant media content that is added to the fragment. Purpose is to expose channel
producers to only this curated media content during production rather than the entire
repository.

Content Fragments do not contain any layout and design beyond rich text formats.
Fragments are pure content. Experiences are created by combing fragments with AEM
components when authoring them in a page or other channel (mobile, email, etc.).
Components add layout and design.

Note:

Fragments + Components = Experiences

CREATE A CONTENT FRAGMENT

Create a new content fragment by using this text:

Cycling is Awesome

Cycling is essentially the perfect outdoor activity. With limitless bike options and
seemingly endless trail choices, cycling accommodates all fitness levels and age
groups, Chose your own adventure.

97
Adobe Experience Manager Developer Guide

This fragment uses a "Simple" template provided with AEM. This template provides for
a single element,
named Main.

To create a Content Fragment, perform these steps:

1. Open the AEM Assets view at


http://localhost:4502/assets.html/content/dam/geometrixx#.

2. Create a new folder named ContentFragments by clicking Create, Folder.

3. Switch to the ContentFragments folder.

4. Click the Create and select Content Fragment from the drop-down menu.

Create Fragments

5. In the New Content Fragment wizard, select the Simple Fragment template and
click the Next.

6. Specify biking as the title and editorial content about riding bicycles as the
description.

98
Adobe Experience Manager Developer Guide

7. Click on the Tag icon to open the Tag Selector and select Geometrixx-Outdoors >
Activity > Biking.

8 Click the checkmark icon to add the tag to the fragment.

9. Click the Create button.

10. When the Success dialog appears, click Open.

11. Paste the biking text that is specified at the start of this article.

EDIT TEXT WITHIN THE CONTENT FRAGMENT

You can edit text defined in content fragments. For example, you can define headings.
To edit text defined in content fragments, perform these steps:

1. In the Content Fragment view, click Edit.

Edit content fragments

99
Adobe Experience Manager Developer Guide

2. At the start of the content - type Cycling is Awesome.

3. Select Cycling is Awesome.

4. Click on the Paragraph icon to open the paragraph style drop-down list and select
Heading 3.

Rich Text Editor in Content Fragments

5. Click the checkmark icon to save the changes.

CREATE A VARIATION

You can create a channel-specific variation of this fragment for use in different AEM applications. In this example, a
mobile variation is created, as shown in the following illustration.

100
Adobe Experience Manager Developer Guide

Mobile variations

To create a variation, perform these steps:

1. Click on the Variations link (in the left pane) and click Create Variation.

Create Variation button

101
Adobe Experience Manager Developer Guide

2. In the New Variation dialog, specify the mobile as the title and shortened content
for the mobile channel as the description.

3. Add the sentence This is mobile to the text to the end of the text.

4. Click the checkmark icon to save the changes.

ASSOCIATE AN ASSET COLLECTION TO A CONTENT FRAGMENT

You can link an Asset Collection to a content fragment by performing these steps:

1. Click the Edit link in the top corner to open the drop-down list.

2. Select Associated Content.

Associated Content

3. Click the Associate Content button to open the Collection Selector.

102
Adobe Experience Manager Developer Guide

Collection Selector

Note:

If you do not see an Asset Collection, create a new one. For details, see Managing Collections.

4. Click on the arctic collection to select it and click the checkmark icon to associate the
collection with this fragment. You will now see the assets associated with this fragment.

103
Adobe Experience Manager Developer Guide

Select an Asset Collection

5. Finally, click the checkmark in the top right corner to save the Content Fragment. This
takes you back to the Assets Admin.

SET CONTENT FRAGMENT METADATA

You can set Content Fragment metadata by performing these steps:

1. From the menu in the left hand side, select Metadata.

104
Adobe Experience Manager Developer Guide

Metadata menu option

2. Click on the Tag icon to open the Tag Selector and select Geometrixx-Outdoors
> Season > Summer.

3, Click the checkmark icon to add the tag to the fragment.

4. Click the checkmark in the top right corner to save the Content Fragment.

USE A CONTENT FRAGMENT IN A WEB PAGE

You can add a content fragment to an AEM web page by performing these tasks:

1. Add a Content Fragment in a web page

2. Specify different paragraphs to be displayed in a web page.

3. Add associated assets from a Content Fragment to a web page

105
Adobe Experience Manager Developer Guide

OPEN THE WEB PAGE IN THE PAGE EDITOR

In this section, you can use the AEM Sites Page Editor to add the Content
Fragment into a web page.

Perform these steps:

1. To start, switch to the Page Editor browser tab for the Biking web page at:

http://localhost:4502/editor.html/content/geometrixx-
outdoors/en/activities/cajamara-biking.html

Biking Page

106
Adobe Experience Manager Developer Guide

Note:

If the side panel on the left side of the screen is not visible, click the Toggle Side Panel button
(furthest to the left) in the top toolbar.

ADD A CONTENT FRAGMENT IN THE PAGE

You can add a Content Fragment in an AEM web page by performing these steps:

1. From the components section under the General category, select Content Fragments
and drag and drop this component onto the page.

Dragging the Content Fragments component

2. In the side panel, switch to the Asset Finder (if it is not displayed). In the type
selector, select Content Fragments, as shown in this illustration.

107
Adobe Experience Manager Developer Guide

Content Fragments

3. The biking Content Fragment appears.

The Content Fragment is displayed

108
Adobe Experience Manager Developer Guide

4. Drag the biking Content Fragment into the Content Fragment drop area (that you
dropped in step 1) in the page. Click on the first header to reveal the component’s
toolbar.

5. Click on the Wrench icon to open up the component’s dialog.

6. Select the Range radio button and enter 1 as the paragraph range.

Content Fragment dialog

USE ASSOCIATED ASSET S

You can add additional assets to a content fragment, which is known as an associated
asset. Perform these steps:

1. In the side panel, switch to the Components list.

109
Adobe Experience Manager Developer Guide

Components located in the side rail

2. Drag and drop the Image - Sightly component above the header Cycling is
Awesome.

Dragging the Sightly Image component

110
Adobe Experience Manager Developer Guide

3. In the side panel, switch to the Associated Assets list. Drag and drop the an image
into the Image component.

Dragging an image

Congratulations, you have just created AEM 6.2 content fragments.

111
Adobe Experience Manager Developer Guide

EXPERIENCE FRAGMENT IN AEM

An Experience Fragment is a group of one or more components including content and layout
that can be referenced within pages. They can contain any component.

An Experience Fragment:

 Is a part of an experience (page)?


 Can be used across multiple pages.
 Is based on a template (editable only) to define structure and components.
 Is made up of one or more components, with layout, in a paragraph system.
 Can contain other experience fragments.
 Can be combined with other components (including other Experience Fragments) to form a
complete page (experience).
 Can have different variations, which may share content and/or components.
 Can be broken down into building blocks that can be used across multiple variations of the
fragment.

You can use Experience Fragments:

 If an author wants to re-use parts (a fragment of an experience) of a page, they need to copy and
paste that fragment. Creating and maintaining these copy/paste experiences is time-consuming
and prone to user errors. Experience Fragments eliminate the need for copy/paste.
 To support the headless CMS use-case. Authors want to use AEM only for authoring but not for
delivering to the customer. A third party system/touchpoint would consume that experience and
then deliver to the end user.

Note:

Write access for experience fragments requires the user account to be registered in the group:

experience-fragments-editors

Please contact your system administrator if you are experiencing any issues.

WHEN SHOULD YOU USE EXPERIENCE FRAGMENTS?

Experience Fragments should be used:

 Whenever you want to reuse experiences.


o Experiences that will be reused with same or similar content
 When you use AEM as a content delivery platform for third parties.
o Any solution that wants to use AEM as the content delivery platform
o Embedding content in third party touchpoints
 If you have an Experience with different variations or renditions.
o Channel or context-specific variations

112
Adobe Experience Manager Developer Guide

o Experiences that make sense to group (for example a campaign with different experiences
across channels)
 When you use Omnichannel Commerce.
o Sharing commerce-related content on social media channels at scale
o Making touchpoints transactional

CREATING AN EXPERIENCE FRAGMENT

To create an Experience Fragment:

1. Select Experience Fragments from the Global Navigation.

2. Select Create. You can create Folders and/or Experience Fragments.

Creating folders allows you to create a meaningful structure for your Experience
Fragments.

113
Adobe Experience Manager Developer Guide

3. From the required folder, select Create then Experience Fragment to open the Create
Experience Fragment wizard.

Select the required Template, then Next:

Note:

You can use the template editor to create your own template.

114
Adobe Experience Manager Developer Guide

Only editable templates can be used; static templates are not fully compatible.

4. Enter the Properties for your Experience Fragment.

A Title is mandatory. If the Name is left blank it will be derived from the Title.

5. Click Create.

A message will be displayed. Select:

o Done to return to the console


o Open to open the fragment editor

EDITING YOUR EXPERIENCE FRAGMENT

The Experience Fragment Editor offers you similar capabilities to the normal page Editor. See
Editing Page Content for more information on how to use it.

The following example procedure illustrates how to create a teaser for a product:

1. Drag and drop a Category Teaser from the Components Browser.

115
Adobe Experience Manager Developer Guide

2. Select Configure from the component toolbar.


3. Add the Asset and define the Properties as required.
4. Confirm the definitions with Done (tick icon).
5. Add more components as required.

CREATING AN EXPERIENCE FRAGMENT VARIATION

You can create variations of your Experience Fragment, depending on your needs:

1. Open your fragment for editing.


2. Open the Variations tab.

116
Adobe Experience Manager Developer Guide

3. Create allows you to create:


o Variation
o Variation as live-copy.
4. Define the required properties:
o Template
o Title
o Name; if left blank it will be derived from the Title
o Description
o Variation tags

5. Confirm with Done (tick icon), the new variation will be shown in the panel:

117
Adobe Experience Manager Developer Guide

USING YOUR EXPERIENCE FRAGMENT

You can now use your Experience Fragment when authoring your pages:

1. Open any page for editing.

For example: http://localhost:4502/editor.html/content/we-retail/language-


masters/en/products/men.html

2. Create an instance of the Experience Fragment component, by dragging the component


from the Components browser to the page paragraph system:

118
Adobe Experience Manager Developer Guide

3. Add the actual Experience Fragment to the component instance; either:


o Drag the required fragment from the Assets Browser and drop onto the component
o Select Configure from the component toolbar and specify the fragment to use, confirm
with Done (tick)

119
Adobe Experience Manager Developer Guide

Note:

Edit, in the component toolbar, operates as a shortcut to open the fragment in the
fragment editor.

BUILDING BLOCKS

You can select one or more components to create a building block for recycling within your
fragment:

Creating a Building Block

To create a new Building Block:

1. In the Experience Fragment editor, select the components you want to re-use:

2. From the components toolbar, select Convert to building block:

120
Adobe Experience Manager Developer Guide

For example:

3. Enter the name of the Building Block, and confirm with Convert:

121
Adobe Experience Manager Developer Guide

4. The Building Block will be shown in the tab, and can be selected in the paragraph
system:

Managing a Building Block

Your building block is visible in the Building Blocks tab. For each block, the following actions
are available:

 Go to master: open the master variation in a new tab


 Rename
 Delete

122
Adobe Experience Manager Developer Guide

Using a Building Block

You can drag your building block to the paragraph system of any fragment, as with any
component.

THE PLAIN RENDITION

Using the .plain. selector in the URL, you can access the plain HTML rendition.

This is available from the browser, but its primary purpose is to allow other applications (for
example, third party web apps, custom mobile implementations) to access the content of the
Experience Fragment directly, using only the URL.

The plain HTML rendition adds the protocol, host and context path to paths that are:

 of the type: src, href, or action


 or end with: -src, or -href

For example:

.../brooklyn-coat/master.plain.html

Note:

Links always reference the publish instance. They are intended to be consumed by third parties,
so the link will always be called from the publish instance, not the author.

123
Adobe Experience Manager Developer Guide

124

Das könnte Ihnen auch gefallen