Customize Adobe Experience Manager
Customize Adobe Experience Manager
Experience Manager
student guide
If this guide is distributed with software that includes an end user agreement, this guide, as well as the software described in it,
is furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted
by any such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by
any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems
Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with
software that includes an end user license agreement.
The content of this guide is furnished for informational use only, is subject to change without notice, and should not be
construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or
liability for any errors or inaccuracies that may appear in the informational content contained in this guide.
Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to
any actual organization.
Adobe, the Adobe logo, Acrobat, the Creative Cloud logo, and the Adobe Marketing Cloud logo are either registered
trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA.
Notice to U.S. Government End Users. The Software and Documentation are “Commercial Items,” as that term is defined at 48
C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such
terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R.
§§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software
Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights
as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the
copyright laws of the United States. Adobe agrees to comply with all applicable equal opportunity laws including, if
appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment
Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41
CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding
sentence shall be incorporated by reference.
Introduction
Adobe Experience Manager (AEM) is a content management system that helps you build and
• Install and run AEM instances by using the command line method
AEM architecture stack is based on technologies such as OSGi, Java Content Repository (JCR), and
Apache Sling.
The following diagram depicts a high-level view of the AEM architecture stack:
Granite is a general-purpose platform for building robust scalable applications. It is Adobe's open
web stack, and forms the technical foundation on which AEM is built. Granite supports an open
architecture, which is based on both open standards (JCR and OSGi) and open source projects
(Apache Sling and Apache Jackrabbit).
Note: Granite is an open development project within Adobe but not an open source project.
• OSGi Compendium Services to support building applications, such as Log Service, Http Service,
Event Admin Service, Configuration Admin Service, Declarative Services, and Metatype Service.
Extend and Customize Adobe Experience Manager 8
• A comprehensive Logging Framework providing various logging APIs, such as SLF4J, Log4F,
Apache Commons Logging, and OSGi Log Service.
Granite UI
The consoles in the main navigation, tools, and editors of AEM are built using the Granite UI. The
Granite UI provides a foundational UI framework for:
• UI widgets
• Extensible
• Easy to override
Note: The Granite UI is based on Coral 3, which is Adobe’s universal UI across all products.
OSGi Framework
OSGi enables a collaborative and modular environment, where each application may be built and
implemented as a small bundle. Each bundle is a collection of tightly coupled, dynamically
loadable classes, JAR files, and configuration files that explicitly declare their external dependencies.
Note: OSGi used to stand for Open Service Gateway Initiative, but that name has been discontinued,
and it is now officially no longer an abbreviation. It is just known in the industry as OSGi.
All content is stored in the content repository, which means backup is done at the repository level.
OSGi runtime hosts Java applications that can access the repository by using the JCR API. As part of
the application runtime, you get Apache Sling, a RESTful web application framework that exposes
the full repository content using HTTP and other protocols.
Apache Felix is an open source implementation of OSGi for the AEM framework. It provides a
dynamic runtime environment, where the code and content bundles can be loaded, unloaded, and
reconfigured at runtime.
JCR
The JCR, specifically Java Specification Request-283 (JSR- 283), is a database that supports
structured and unstructured content, versioning, and observation. In other words, it is a database
that resembles a file system.
Note: The Adobe implementation of JSR-283 was known as the Content Repository eXtreme (CRX).
Hence, you may see CRX in some tools and interfaces in AEM. However, the CRX as a feature is being
phased out. In its place, AEM uses the Granite platform and Apache Jackrabbit Oak.
All data pertaining to AEM, such as HTML, HTML Template Language (HTL), CSS, JavaScript/Java,
images, and videos are stored in the JCR object database. JCR is built with Apache Jackrabbit
Oak, an open-source project.
AEM also works with other JCR repositories, such as Apache Jackrabbit 2.x, and with a number of
non-JCR data stores through connectors. Therefore, it is capable of pulling content from its built-
Extend and Customize Adobe Experience Manager 10
in Oak repository and any JCR- compliant source, such as a third-party repository (for example,
Jackrabbit 2.x) or a connector that exposes the legacy storage through the JCR.
The advantages of using JCR are:
• It provides a generic application data store for structured and unstructured content. While file
systems provide excellent storage for unstructured and hierarchical content, the databases provide
storage for structured data. This way, JCR provides the best of both the data storage architectures.
• It supports namespaces. Namespaces prevent naming collisions among items and node types that
come from different sources and application domains. JCR namespaces are defined with a prefix,
delimited by a single colon (:). For example, jcr:title. This means that this title property is defined in
the jcr namespace.
Apache Sling
Apache Sling is a web application framework for content-centric applications and uses a JCR, such
as Apache Jackrabbit Oak, to store and manage content.
The key features of Apache Sling include:
• It is Apache open source.
• It is based on REST principles and helps build applications as a series of OSGi bundles.
A request URL is first resolved to a resource, and then based on the resource, Apache Sling selects
the Servlet or script to handle that request. Servlets and scripts are handled as resources and are
accessible by a resource path. This means every script, Servlet, filter, and error handler is available
from the Resource Resolver just like normal content—providing data to be rendered on request.
• AEM Assets (Digital Asset Management, Assets Sharing and Dynamic Media Delivery)
• Content Services
• Workflows
The above application functions/modules sit on top of the Granite platform. They share the same
infrastructure and UI framework. These modules are encapsulated within the OSGi container and
are very tightly integrated with each other.
In AEM terminology, an instance is a copy of AEM running on a server. AEM installations usually
involve running at least two instances:
• Author: An AEM instance used to create, upload, and edit content and administer the website.
• Publish: An AEM instance that serves the published content to the public.
Note: The Dispatcher is a static web server, such as Apache httpd and Microsoft IIS, augmented
with the AEM Dispatcher module. It caches webpages produced by the publish instance to improve
performance.
• Minimum 4 GB of RAM
During installation, you will notice that the JAR file creates a root folder on your system called
Note: After installation is complete, the quickstart file is referred to as the AEM startup file.
Note: Windows users may need to ensure their system’s environment variables are set
appropriately to run Java 1.8 before installing AEM. Open a command prompt and type java -
version to ensure Java is set up properly. When you run the command, it should show the
following result
(java version “1.8.0_144”):
This method involves using the *.jar file to start an AEM instance. In a Windows or Mac OS
environment, you can double-click the aem-author-4502.jar file to start an author instance, or the
aem-publish-4503.jar file to start a publish instance.
The installation will take approximately 5-7 minutes the first time, depending on your system’s
capabilities.
After AEM starts, your default browser will open a new tab automatically, pointing to AEM’s start
URL (where the port number is the one you defined on installation).
Command Line Method
When you use the command line method to install and start, you can provide additional
performance-tuning parameters to the Java Virtual Machine (JVM) and perform other
administrative tasks. On Windows, MacOS X, or *x, you can increase the Java heap size during the
installation, which improves performance.
• Using the Command Line to Install and Start an AEM Author Instance
Prior to the installation, you may want to know which parameters are available to configure
quickstart. Enter the following command in the command prompt to display a complete list of
optional parameters:
java -jar aem-author-4502.jar -h
The AEM quickstart installer will show all the available command-line options without starting the
server.
Default value 64 MB for a JVM running on 32-bit machines, or 83 MB for 64-bit machines
Example:
java -Xms512m -Xmx1024m -jar aem-author-4502.jar
• Using the Command Line to Install and Start an AEM Publish Instance
If you want to install and start your AEM publish instance using a command prompt, navigate to
the directory containing your quickstart jar file (such as \adobe\AEM\publish), and enter the
following command to install the publish instance:
java -jar aem-publish-4503.jar
• Using the Command Line to Start AEM with the nosamplecontent Run Mode
A run mode is a collection of AEM configuration parameters that allow you to tune your AEM
instance for a specific purpose. nosamplecontent is a predefined run mode available in AEM.
Note: The author and publish instances are the same software stack but two different run
modes.
After you install AEM using a graphical or command line method, you can use the built-in batch
files in the crx-quickstart directory to start AEM. You can also configure the start up and additional
options using these batch files.
Navigate to your install directory and then to the crx-quickstart directory that was created as part of
your installation. Within \crx-quickstart\bin subdirectory, there are batch files (on Windows
systems) available for you to start or stop AEM, and get status information on the server. The server
parameters provided in these batch files are documented using comments or commented-out as
appropriate in the case of options that you may want to set for your instances.
In this task, you will install and start your AEM author instance on port 4502.
Note: If you are attending a v/ILT class using ReadyTech, steps 1 through 3 were completed for
you. Skip ahead to step 4.
a. Windows: C:/adobe/AEM/author
2. Copy the aem-quickstart-6.4.0.jar and license.properties files, from the location provided
by your instructor, to your newly created directory.
• aem = Application
• author = Web Content Management (WCM) mode AEM will run in (in this
case, author)
• 4502 = Port AEM will run in
4. You can, therefore, control the way AEM is installed by defining properties in a filename.
Note: When running for the first time, the quickstart *.jar will notice that it has to install
AEM.
By renaming the file, you use a convention of passing the instance name
(Webpathcontext) and port number through the file name, so no user interaction is
needed during the installation process.
If no port number is provided in the file name, AEM will select the first available port from
6. After the AEM Author instance has started successfully, the start-up screen (the GUI) will
change to something similar to the following:
Note: To stop the AEM instance, click the ON/OFF toggle button in the GUI.
8. Now, each time you want to run your AEM author instance, follow the same procedure in
step 4 to start it. However, this time, the startup will be as fast as one minute or less, as the
initial installation task has been performed.
9. In addition, after AEM starts, your default browser will automatically open to AEM’s start URL
(where the port number is the one you defined on installation). For example:
http://localhost:4502
Note: Notice, a crx-quickstart directory is also created on your computer as shown below:
In this task, you will install and start an AEM publish instance on port 4503. The publish instance is
a separate run mode where your published content resides for access on the web.
Note: If you are attending a v/ILT class using ReadyTech, steps 1 through 3 were completed for
you. Skip ahead to step 4.
2. Copy the aem-quickstart-6.4.0.jar and license.properties files, from the location provided
by your instructor, to your newly created directory.
• aem = Application
• publish = Web Content Management (WCM) mode AEM will run in (in this
case, publish)
• 4503 = Port AEM will run in
Note: If you have multiple author and publish instances, a best practice to consider is using
an even/odd numbering paradigm for port numbers.
So, your author instances would be:
• 4502, 4504, 4506, …
And, your publish instances would be:
5. After the initial installation, each time you start an AEM instance (author or publish), it will
take 1-2 minutes.
6. After the AEM publish instance has started successfully on port 4503, the start-up screen (the
GUI) will change to something like the following:
Tip: You do not need to manually sign in as the publish instance loads the
We.Retail reference site immediately.
In this task, you will start and stop an AEM author instance using the command line method.
Note: You already have an author instance and a publish instance running. To stop your author instance,
click the ON/OFF toggle button in the GUI window.
9. Prior to the installation, you may want to know which parameters are available to configure
the AEM quickstart. Enter the following command to display a complete list of optional
parameters you can use to install and start AEM (this command will not install and start
AEM):
11. Your AEM instance should start up again, and this time with a command window available
to view details of the startup. In addition, the GUI window will also be available for you to
shut down AEM.
In this task, you will install AEM without the We.Retail site using the nosamplecontent run mode
and change the admin password.
To begin installation:
1. Create a separate sibling directory called nosamplecontent on your machine in the same
location as your author and publish directories.
2. In Windows (and also if you are using ReadyTech), this would be:
C:\adobe\AEM\nosamplecontent
3. Copy the quickstart *.jar file and the license.properties file from your author directory and
5. Open a command prompt in the directory where your quickstart *.jar file is copied.
• With the author and nosamplecontent run modes (that is, an author environment
without the We.Retail sample site)
9. As this is the first time you are installing an instance of AEM using the command line, a
prompt should appear asking you to enter the admin password:
Tip: As you did not use the -gui option, no startup window will appear on your
computer to show the progress as AEM installs and loads. Therefore, you will
need to wait for your new browser tab localhost:4504 to appear and signal that
AEM has started.
12. After the initial installation and startup of AEM, enter your new admin password (instead of
admin/admin) to confirm that you can log in and that the We.Retail site does not appear:
13. To confirm that We.Retail site does not appear in the AEM navigation, click Sites on the
default Navigation page. Notice that We.Retail does not appear when you click it (it should
only show options such as Screens, Campaigns and Community Sites):
Note: You need to use this method to stop AEM because you are not using the -gui parameter.
Therefore, the GUI window is not available for you to stop AEM.
15. Start your author instance on port 4502 again, either using the JAR file method described in
Task 1.1 or using the command line method described in Task 1.3.
The AEM UI combines the advantages of a web interface with the fluidity and responsiveness that
is usually associated with desktop applications. It is touch-optimized for authoring across desktop
and mobile devices.
Device UI Desktop UI
Actions Actions
Tap Click
Touch-and-hold Double-click
Swipe Hover
When you start your author instance and sign in to AEM, you are presented with a start screen that
includes the header bar and the content area.
The content area, by default, displays all applications and capabilities of AEM, such as Projects,
Sites, Experience Fragments and Assets.
There are two main sections in the AEM UI: Navigation and Tools.
• Navigation
The Navigation section is represented by a compass icon in the AEM UI. By default, when you first
sign in, the Navigation section loads in the content area. All applications of AEM, such as Projects,
Sites, Experience Fragments, Assets, and Forms, are available in this section. This is also the main
section relevant to AEM authors to manage and build content for AEM Sites or leverage assets.
To create a page in AEM Sites, you need to follow a simple wizard where the page template is
specified, and the page is given a title and a name. The title is displayed to the user and the name is
used to generate the page URL (and can be derived from the title).
After you create a page, you can edit and add content to it. You can add content by draging the
components available in the side panel onto your page in the page editor.
AEM Keyboard shortcuts
When you select an object in AEM such as a page, the header bar changes to show a menu of
options to work with the object. To aid in editing and managing pages, there are a collection of
keyboard shortcuts you can use to quickly access common tasks and functions, as shown below.
By default, each user’s keyboard shortcuts are enabled.
We.Retail is an example retail outdoor equipment reference site that comes with AEM. The
purpose of We.Retail is to show the recommended way of setting up an online presence with AEM
Sites. This site is built with the following best practices of AEM:
• Localized site structure, with language masters live-copied into country-specific sites
• Content fragments
• Core components
Note: While We.Retail illustrates a retail vertical, only the product catalog and cart features are retail
specific. The site is set up in a way that it can be applied to any vertical.
In this task, you will create a demo page using the content template available in AEM.
To create a new page:
1. Ensure you have started and logged on to your AEM author instance on port 4502.
2. The Navigation page is displayed by default in the content area. Click Sites as shown below:
Note: You may see the Product Navigation tutorial dialog guiding you through the navigation.
You may click Next to proceed through the tutorial and learn the basic AEM UI elements and
navigation, or you may click Close to hide the tutorial.
6. After you click Page, a wizard appears where you need to select a template for your page.
Extend and Customize Adobe Experience Manager 35
7. Click the Content Page template to select it, and click Next as shown:
8. In the Properties step of the page creation wizard, enter the following values for the
• Name: demoPage
9. Click Create in the top-right corner to create the page. A Success dialog box is displayed
with a message that your page has been created.
In this task, you will edit the page you just created by adding text and image components.
To edit the page:
1. Click the Demo Page (thumbnail) you just created to select it, and click Edit from the
actions bar. Be patient as it may take a few minutes to load the AEM page editor the first
time.
4. Click the Toggle Side Panel icon in the top-left corner as shown:
7. In the Filter field, enter text to search for the Text component, and press Enter. The search
yields results that contain the word ‘text’.
8. Drag the Text (We.Retail) component into the Drag components here box as shown:
9. Click the Text component, and then click Edit (pencil icon) from the component toolbar as
shown. A text editor opens in the same tab.
10. Add sample text of your choice in the text editing form that appears, and click Done
(checkmark icon) to save the changes. The text is added to the page.
12. You have now added the first component to your page!
15. Click Preview in the top-right corner to preview the changes to your page:
16. Press CTRL+SHIFT+M to go back to the edit mode. You may use this method to toggle
between Preview and Edit mode, as you may need to switch often when adding and testing
page content.
Note that this keyboard shortcut is AEM specific and does not depend on the operating
system or the browser. In other words, this shortcut is universal to AEM.
Note: At this time, your page has been edited, but is not yet live. In order to push changes to
content to the web, your page has to be published (or activated) to a publish instance of AEM.
2. Web Console
3. Package Manager
CRXDE Lite
Note: CRXDE Lite is primarily used by front-end developers who develop components and client
libraries in AEM. DE in CRXDE stands for Development Environment.
development.
• Product training
• Operations debugging
• Explorer pane: Displays a folder tree structure of all the nodes in the repository
Select the node and view its properties in the Properties tab. Examine all the JCR
properties of different nodes.
Right-click the node and perform an action on it, such as renaming the node, creating
a new node, creating a folder, and creating a file.
• Properties tab: Displays the properties of the node that you selected. You can add new properties
or delete existing ones.
Note: If you use the navigation in AEM, the Web Console and CRXDE Lite always open in a new tab in
The Web Console contains a selection of tabs for maintaining OSGi bundles. The most important
menu selections under the OSGi tab are:
• Bundles- Used for installing and managing bundles.
• Components- Used for managing and controlling the status of components required for AEM.
• Configuration- Used for configuring OSGi bundle, and is the underlying mechanism for
configuring AEM parameters.
A package is a *.zip file that holds AEM repository content in the form of a file-system serialization
called Vault serialization. Vault is provided by Apache Jackrabbit.
Packages provide an easy-to-use-and-edit representation of files, such as pages, assets, and folders.
They also enable you to import and export repository content from one instance or environment
to another.
A package can contain:
• Page-related content
• Project-related content
• Assets-related content
Extend and Customize Adobe Experience Manager 47
• Vault meta information, such as filter definitions and import configuration information
• Other package information such as package settings, package filters, package screenshots, and
package icons
Package Manager
Package Manager is used to import or export content on your instance, transfer content between
instances, and back-up repository content. With Package Manager, you can perform the following
common tasks:
• Create, build, and download content packages
You can also use filters to create a package containing page content or project-related content.
When creating packages using Package Manager, you can apply rules and filters to determine the
content a package should extract from the repository. After you define the content, you can build it.
A package is created in a .zip file and you can download it to your local file system. You can test the
contents of the package before building it.
There are many options in Package Manager to work with packages, such as:
• Rebuild: Helps rebuild the package if there is a change in the repository content.
You can download a package by clicking the download link. This link is displayed when the
package details are expanded. After downloading the package, you can unzip the contents of the
package to your local system.
Typically, an unzipped (extracted) content package contains the following folders:
• jcr_root: Contains files and folders that are serialized nodes and properties from the JCR.
• META-INF: Contains metadata regarding node definitions and the filter.xml file that gives
directions to Vault about the paths to include.
Package Share
Package Share is a centralized server where public packages are made available. These packages
may include hotfixes, new functionality, updates or documentation. You can search, download, and
install any package either to your instance or to your local file system.
Within the Package Share, you have access to the following:
• AEM packages provided by Adobe (For example, new functionalities such as updated core
components, hotfixes and service packs)
In this task, you will validate and install a package using the Package Manager.
To validate a package:
1. Ensure that you are logged on to your AEM author instance on port 4502
2. Navigate to Tools > CRXDE Lite in your AEM author instance as shown:
7. In the Upload Package dialog box, click Browse and select the SamplePackage.zip package
from the Exercise_Files (in the \Module 4 – Package Manager folder) provided to you.
15. Check the Activity Log. You can see the content was added from the package. In the activity
log, note that the contents of the package consist of a set of image assets being added to
/content/dam/assets-from-sample-package in the JCR repository.
20. In your other browser tab, navigate back to the AEM start (http://localhost:4502).
Note: You may see a Product Navigation tutorial dialog guiding you through the navigation.
You may click Next to proceed through the tutorial and learn the basic AEM user interface
elements and navigation, or you may click Close to hide the tutorial.
In this task, you will use the Package Manager to package We.Retail content for distribution to
another environment.
To create a package:
1. In your CRXDE Lite browser tab, click the Package Manager icon as shown:
• Version: 1.0
• Group: training
Note: Filters are the mechanism used to add content to packages. Here, you specify the paths
that contain the content from the JCR you want to include in a package. Before adding filters,
you package is completely empty. You may also restrict filetypes added to a package using
filter rules, such as excluding all *.txt files.
8. For the Root path, browse and select the weretail project folder under apps, and click OK.
Note: As the package is being built, the activity log is running at bottom, showing a series of
“A” actions in the log. “A” denotes a node is being added to the content package.
11. Click Build again in the confirmation dialog box. The package is now ready for download.
12. Click the Download link to download a copy of the package to your computer. The package
is download to your computer’s default download folder for the browser.
Authoring:
• You can download the latest release of the We.Retail site using the following link:
https://github.com/Adobe-Marketing-Cloud/aem-sample-we-retail/releases
Developer Tools:
• Package Share Direct URL (No need to access through CRXDE Lite):
https://www.adobeaemcloud.com/content/packageshare.html
Introduction
You can use Maven and Eclipse to configure Adobe Experience Manager (AEM) development
environment. Maven builds and deploys bundles to Java Content Repository (JCR), and Eclipse helps
Maven is the recommended build management tool for AEM projects. The following steps are required to
develop an AEM project in Eclipse:
• Install Eclipse
Objectives
• Describe Maven
• Usage of Apache Sling and Apache Felix tool sets for Maven-based development setups
POM files are XML files that contain the identity and the structure of the project, build
configuration, and other dependencies. When executing a task or goal, Maven looks for the POM in
the current directory. Maven reads the POM, gets the needed configuration information, then
executes the goal. A typical POM file includes:
• General project information: This section includes the project name, website URL, and the
organization name. It can also include a list of developers, contributors along with the license
for a project.
• Build settings: This section includes the directory settings of source and tests, plugins, plugin
goals, and site-generation parameters.
• Build environment: This section includes the profiles that can be used in different
environments. The build environment customizes the build settings for a specific environment
and is often supplemented by a custom settings.xml file in the Maven repository. A Maven
repository is a directory that stores all project files, including JAR files, plugins, artifacts, and
other dependencies.
o GroupId
o ArtifactId
o Version
o Dependencies
Super POM
The default Super POM defines a single remote Maven repository with an ID of central. This is the
central repository that all Maven clients are configured to read from by default. A custom
settings.xml file can override this setting.
• Snapshot versions: This section includes snapshot versions used for projects under active
development. Snapshot versions are indicated by the string ‘-SNAPSHOT’. If a project depends
on a software component that is under active development, you can depend on a snapshot
release and Maven will periodically attempt to download the latest snapshot from the
repository when you run a build.
• Property references: This section includes the properties from another part of the POM file,
Java system properties, or implicit environment variables. It supports three environment
variables:
o env
o project
o settings
• Plugins: This section includes plugins that provide functionalities, such as compiling source,
packaging a WAR file, or running JUnit tests. These plugins are retrieved from the Maven
repository. If a new functionality is added to a plugin, you can use it by updating the version
number of the plugin in a single POM configuration file.
UberJar is a special JAR file provided by Adobe to reduce the number of dependencies. Earlier, for
every API being used, a separate and individual dependency had to be added to the project.
The UberJar file contains:
• All public Java APIs exposed by AEM
• Limited external libraries—all public APIs available in AEM, which comes from Apache Sling,
Apache Jackrabbit, Apache Lucene, Google Guava, and two libraries used for image processing
• A MANIFEST.MF file with the correct package export versions for all exported packages
To use the UberJar file, you must add the following elements to the pom.xml file:
• Dependency element: To add the actual dependency to your project
a. <dependency>
b. <groupId>com.adobe.aem</groupId>
c. <artifactId>uber-jar</artifactId>
d. <version>6.4.0</version>
e. <classifier>apis</classifier>
f. <scope>provided</scope>
g. </dependency>
• Repository element
1. <repositories>
2. <repository>
3. <id>adobe-public-releases</id>
5. <url>https://repo.adobe.com/nexus/content/groups/public/</url>
6. <layout>default</layout>
7. </repository>
8. </repositories>
Extend and Customize Adobe Experience Manager 64
9. <pluginRepositories>
10. <pluginRepository>
11. <id>adobe-public-releases</id>
13. <url>https://repo.adobe.com/nexus/content/groups/public/</url>
14. <layout>default</layout>
15. </pluginRepository>
16. </pluginRepositories>
The AEM perspective offers complete control over all your AEM projects and instances.
NOTE: You can skip this exercise if you use a ReadyTech environment because AEM is already
installed as part of the image.
2. Navigate to the directory where you extracted the contents of the Eclipse installation zip file. For
example, navigate to C:\Program Files\Eclipse\ on Windows or Applications/Eclipse on Mac.
3. Double-click eclipse.exe (or eclipse.app) to start Eclipse. The Eclipse Launcher opens, as shown:
1. Click the Workbench logo in the upper-right corner, as shown, to close the welcome screen and
go to the main workbench.
You should see a path similar to the one given in the following screenshot. Otherwise, you must
provide the correct directory path to your JDK.
NOTE: You can skip this exercise if you use a ReadyTech environment because AEM is already
installed as part of the image.
• Online: You will provide the link to install the plug-in in Eclipse.
2. Double-click eclipse.exe (or eclipse.app) to start Eclipse. The Eclipse Development Environment
opens.
3. Select Help > Install New Software, as shown. The Install window opens.
5. Click Archive.
6. Navigate to the repository archive and select the zip file (com.adobe.granite.ide.p2update-1.2.0.zip)
provided for the plug-in from Exercise_Files/05_Dev_Environment/.
10. Click the I accept the terms of the license agreements radio button and click Finish. The Installing
Software dialog box with a progress bar opens. The installation should take a minute or two.
12. Click Yes to restart Eclipse to load the newly installed tools.
13. Click Workbench in the upper-right corner again. The Workspace opens.
14. Notice the new AEM perspective available in Eclipse. To check this, click the Open Perspective icon, as
shown:
1. Use the Eclipse icon to the right on the task bar to open Eclipse. The Eclipse Launcher opens.
4. Click Next.
• Name: TrainingProject
Now that you have a basic project from the archetype, you will be able to update the POM files to
support AEM 6.4 and a few dependencies that you will use later in this course.
You will use a text editor (such as Notepad++) and Eclipse to copy and replace the entire contents
of each POM file with updated content from the Exercise Files for the class.
1. In the Exercise Files locate the folder: /05_ Dev_Environment/POM_Files/. Notice the POM files with
names indicate which project they should be used to update. Copy the contents to the matching POM
files in Eclipse as follows:
NOTE: The updated POM files have the following changes to support our project:
The uber-jar was updated from 6.3 to 6.4, which lets retrieve all the correct dependencies for AEM.
A new dependency for core component development is added, as shown:
Parent POM:
• A new dependency for Google Gson for json objects is added, as shown:
Core POM:
3. In Project Explorer, right-click training and select Maven > Update Project. The Update Maven
Project window opens.
5. Select the Force Update of Snapshots/Releases checkbox, and click OK, as shown. Your project is
now updated.
1. Right-click training.core, and select Maven > Select Maven Profiles. The Maven Profile selection
2. In the Select Maven profiles window, select autoInstallBundle and adobe-public (auto
activated) from the Available profiles section, and click OK, as shown. The autoInstallBundle for
training.core is activated.
3. Right-click training.it.launcher, and select Maven > Select Maven Profiles. The Maven Profile
Selection screen is displayed.
6. Select autoInstallPackage and adobe-public from the Available profiles section, and click OK. The
autoInstallPackage for the training.ui.content is activated.
1. Right-click training (parent directory), and select Run As > Maven build... The Edit configuration
and launch dialog box opens.
2. In the Edit configuration and launch dialog box, in the in Goals field, enter clean install and in the
Profiles field, enter: adobe-public, autoInstallPackage, as shown:
NOTE: When the AEM project is first run, Maven will download all required dependencies
4. Verify both ui.apps and ui.content content packages are installed in Package Manager and the core
bundle installed in the Web Console.
2. On the left-hand side of the Eclipse Workspace below Project Explorer, notice the Servers tab. Click
the No Servers are available.
5. Click Next. The Add and Remove resources dialog box opens.
6. Select training.ui.apps and training.ui.content one by one, and click the Add button to move the
specified resources from the Available section to the Configured column, as shown:
8. On the left-hand side of the workspace (below Project Explorer), select the Servers tab and note
how Adobe Experience Manager at localhost [Stopped] is now available, as shown:
9. To modify the configuration for the AEM Server, double-click the Adobe Experience Manager at
Note: The reason to change the AEM port is that your server is running on 4502.
You have now created a connection from Eclipse to the AEM server on your computer
12. Right-click Adobe Experience Manager at locahost on the Servers tab, and click Start. The server is
started.
1. In Eclipse Project Explorer, navigate to: training.ui.apps > src / main /content/jcr_root > apps>
trainingproject > components > content > helloworld.
3. Add the following line at the end of the <pre> tag in the code:
Note: When you save helloworld.html, the AEM Server connection in Eclipse exports
helloworld.html to the JCR.
7. Next, we will make a change in CRXDE Lite and import it back into our Eclipse Project. In CRXDE Lite
and navigate to apps > trainingproject > components > content > helloworld.
8. Right-click helloworld component node, and select Create > Create File.
NOTE: Ensure to click Save All after every change in CRXDE lite.
12. Accept the default settings and click Finish. The selected node and its children are imported from the
server.
NOTE: Step 11 is a very typical process in AEM Java development to sync new content from the JCR
to Eclipse. Remember that Eclipse is our master repository locally and anything created in the JCR
that is a part of our project must be pulled back down into Eclipse. This is a very common process
with config nodes, dialog structures, components, and clientlibs.
IMPORTANT! If you create something in CRXDE Lite that you want to keep, you must sync it
back to Eclipse using the process above.
Introduction
OSGi configurations are used by developers and administrators to manage Adobe Experience Manager
(AEM) instance settings in conjunction with run modes. This course will teach you the use cases and best
practices for creating custom OSGi configurations and run modes.
• Set run modes in the command line when starting or installing AEM
• Create custom OSGi configurations using Java Content Repository (JCR) nodes
Note: The preferred method as per AEM best practices is creating configuration nodes in the JCR.
You can define configurations for each run mode by creating specific nodes by following these
guidelines:
• Create nodes under /apps of type sling:OsgiConfig
Using this method, it is possible to share a configuration among several instances, which is a best
practice in AEM development.
If you modify the configuration data in the repository, the changes are immediately applied to the
relevant OSGi configuration as if the changes were made using the Web Console, with the
appropriate validation and consistency checks. This also applies to the action of copying a
configuration from /libs to /apps.
You should consider these factors before creating configurations:
• Persistent Identity (PID) of the service
• Run modes—Check whether a specific run mode is required. If so, create the folder specific to that
run mode. For example, create a configuration (config) for all run modes, such as config.author for
the author environment and config.publish for the publish environment.
Extend and Customize Adobe Experience Manager 98
• Requirements of configurations or factory configurations
Note: Use this method only for temporary testing in a development environment.
Configuration files are files ending with the extension *.config in the /launchpad directory of your
AEM crx-quickstart directory structure. Although these files can be used to manage OSGi
configurations, it is recommended that you never edit these files to manage OSGi configurations.
This is a risky process and could lead to system instability. If configuration files are accessed, they
should be kept as view-only (or read-only) and only be used for troubleshooting purposes.
It is important to note a few details on how changes to the configurations are persisted:
• By default, you can find any change made to a configuration in /apps/system/config.
• The default settings in AEM are saved in *.config files under /crx-quickstart/launchpad/config.
Warning: You must never edit the folders or files under the /crx-
quickstart/launchpad/config folder.
• Whether a specific run mode is required. Create the following folders based on the run mode:
config.<run-mode>—as appropriate
• The individual parameters to be configured; including any existing parameter definitions that will
need to be recreated. Reference the individual parameter field in the Web Console. The name is
shown in brackets for each parameter.
The following order of precedence is used when resolving configuration nodes upon AEM startup:
1. Repository nodes under /apps/*/config, either with type sling:OsgiConfig or property files
This means project-specific configurations under /apps take precedence over /libs.
Resolution Order at Runtime
Configuration changes made while AEM is running triggers a reload with the modified
configuration. The following order of precedence applies:
1. Modifications made in the Web Console
For run mode-specific configurations, you can combine multiple run modes. For example, you can
create configuration folders in the following style and syntax:
/apps/<your_application>/config.<runmode1>.<runmode2>/
Configurations in these folders will be applied if all run modes match a run mode defined at
startup. For example, if an instance was started with the run modes publish,dev,emea,
configuration nodes in /apps/*/config.emea, /apps/*/config.publish.dev/ and
/apps/*/config.publish.emea.dev/ will be applied, while configuration nodes in
/apps/*/config.publish.asean/ and /config/publish.dev.emea.noldap/ will not be applied.
If multiple configurations for the same PID are applicable, the configuration with the highest
You can run your AEM instance for specific purposes by using specific run modes. For example,
author, publish, test, development, and so on. For run modes, you can:
• Define collections of configuration parameters for each run mode. A basic set of configuration
parameters is applied to all run modes; you can then configure additional sets to meet your
specific environment. These are applied as required.
AEM has built-in author and publish run modes (do not remove these). If required, you can add
additional custom run modes. For example, you can configure run modes for:
• Environment: local, development, test, and production
While you can change run modes after installation, several specific run modes, called installation
run modes, cannot be altered once an AEM instance is installed. These include author/publish and
samplecontent/nosamplecontent. These two pairs of run modes are mutually exclusive
(specifically, AEM can be defined as author or publish, but not both). Author run mode can be
combined with samplecontent and nosamplecontent, but not both at the same time.
Customized run modes can differentiate instances by purpose, stage of development, or location.
Some examples of complex run modes (based on different locations and facilities) are:
• author, development
• publish, test
• author, intranet, us
All settings and definitions are stored in the repository and activated by setting the appropriate run
mode.
It is possible to define specific run mode(s) that a specific instance should run on. By default, an
author instance runs on run mode “author” and a publish instance runs on run mode ”publish”. It is
possible to define several run modes for one instance, such as author, foo, and dev. These run
modes can be set as Java Virtual Machine (JVM) options. For example, to set run modes from the
command line:
Alternatively, in the start script (or batch file used to start AEM):
sling.run.modes=author,foo,dev
Note: It is recommended that as a best practice, you define run modes using the command line, or by editing
the start scripts located in /crx-quickstart/bin/start. It is not recommended to use the sling.properties file to
define run modes.
To create separate configuration settings per run mode in the JCR, create folder names using the
syntax of config.<runmode> for each run mode used. For example, configurations that apply to the
publish run mode would be set in this folder: /apps/myapp/config.publish
For systems with run modes publish and Berlin: /apps/myapp/config.publish.berlin
Configurations for Different Run Modes
Some examples of configuration settings that may be needed for different run modes are:
• Different mail server configurations per location:
config.basel/com.day.cq.mailer.DefaultMailService
config.berlin/com.day.cq.mailer.DefaultMailService
When using different configurations for separate run modes, the following apply:
• Partial configurations are not supported
• Be able to start AEM with a custom run mode using the command line
• Create multiple sets of custom OSGi configurations to match custom run modes in order to specify
different groups of settings for each instance or environment you are deploying
In a typical development process, there are multiple servers designated for specific tasks in your
In this task, you will create a custom OSGi configuration node to change the default “root” start
page (http://localhost:4502) that loads when you sign in to AEM from start.html to sites.html.
1. Ensure your AEM author instance is running and you are logged on.
4. To locate the Root Mapping OSGi configuration, search for the words: Day CQ Root
Mapping in your browser.
6. Copy the value for Persistent Identity (PID). You will create a configuration node for this
configuration in CRDXE Lite using this value under apps as per the best practice to change
9. Right-click the weretail folder and create a new folder node by selecting Create > Create
Folder.
12. Click Save All in the top-right corner to ensure your new folder is saved.
13. Right-click the config.author folder node and create a new node by selecting Create >
Create Node.
Paste the following PID you copied from the Web Console in the Name field:
com.day.cq.commons.servlets.RootMappingServlet
Tip: Ensure there are no whitespaces or bullet points preceding the Name
value. These may be included in the value you copied previously from the
Web Console, so if they do get pasted in, remove them.
15. Click OK, and thenclick Save All in CRXDE Lite to ensure your new node is saved.
Type: String
Value: /sites.html
17. Click Add in the bottom-right corner in the JCR Properties tab to add your property.
18. Click Save All in CRXDE Lite to ensure your property is saved.
Extend and Customize Adobe Experience Manager 109
19. Open a new browser tab and navigate to the AEM author instance (http://localhost:4502).
The Sites page should open, as this is what you configured with your custom configuration
node.
In this task, you will start your AEM author instance using a custom run mode called dev via
command-line.
1. In the AEM Web Console (http://localhost:4502/system/console), navigate to Status > Sling
Settings.
2. Observe the current run modes your author instance is using (s7connect, crx3, author,
samplecontent, crx3tar):
If you are running AEM using the command line, use CTRL+C (in Windows) in your
command window to shut down AEM.
4. Now, you will start AEM using the command line in order to use a custom run mode. This is
because the custom run modes can be generated using command line parameters. Navigate
to the directory on your machine where your author instance quickstart file resides.
5. Start AEM again using the following command that specifies the author and dev run modes:
6. Your AEM instance should start up again, this time with a command window available to
view details of the startup. In addition, the GUI window will also be available.
Tip: Be patient as it may take up to two minutes for your instance to start.
In this task, you will change the default “root” page to load CRXDE Lite for the custom ‘dev’ run
mode.
To create another root mapping OSGi configuration node:
1. Open CRXDE Lite using http://localhost:4502/crx/de or from AEM by navigating to Tools >
CRXDE Lite.
6. Click OK, and click Save All in CRXDE Lite to ensure your new folder is saved.
7. Now, instead of manually creating another root mapping node that is very similar to the one
you created in Task 1.1, you can copy the node you created and paste it into your new folder
and make the necessary changes.
12. Click Save All in CRXDE Lite to ensure your property is saved.
13. To verify if the change was made to the dev run mode, when http://localhost:4502 opens in
your browser and you sign in, it should automatically navigate you to the CRXDE Lite page.
Question: Why does CRXDE Lite now load, but not the Sites page? What command could
you use to start AEM with the Sites page?
Introduction
Adobe Experience Manager (AEM) log files provide detailed information about the current system
state of AEM. It is important to maintain the AEM system, so that the system runs without any
POM files are XML files that contain the identity and the structure of the project, build
configuration, and other dependencies. When executing a task or goal, Maven looks for the POM in
You can channel log messages for a single service into a separate file. AEM uses the following
process to write log messages to a file:
1. The OSGi service (logger) writes a log message.
2. The Logging Logger takes this message and formats it according to your specification.
3. The Logging Writer writes all these messages to the physical file you defined.
Logging Logger and Logging Writer are linked by the following parameters:
Logger (Logging Logger): Defines the service(s) generating the messages.
Log File (Logging Logger): Defines the physical file for storing log messages. This parameter links a
Logging Logger with a Logging Writer.
Log File (Logging Writer): Defines the physical file the log messages will be written to.
The following table lists the standard Writers and Loggers available in AEM:
Apache Sling Logging Logger configuration Does not link to any specific Writer. It creates and
(org.apache.sling.commons.log.LogManager.factor uses an implicit writer with default configuration.
649d51b7-6425-45c9-81e6-2697a03d6be7)
Writes warning messages to logs/error.log for the
service ogr.apache.pdfbox
In the above table, the first logger links to another logger, and the second logger links to the writer.
The third logger does not link to a specific writer, so it creates and uses an implicit writer with
default configuration (daily log rotation).
1. Create a new instance of the Factory Configuration Apache Sling Logging Logger Configuration.
2. Create a new instance of the Factory Configuration Apache Sling Logging Writer Configuration.
Note: The project-trainingproject.log is the custom log file that was created from the AEM
Archetype for this project. By default, all the log messages for this course are located in this log
file.
3. Launch Eclipse by double-clicking the shortcut for Eclipse on your desktop and open your
workspace. The trainingProject opens in the Eclipse Development Environment.
6. Click the JCR Properties tab below the file. The Properties window opens.
8. Log on to AEM with the admin credentials. You are now logged on to the server.
15. Click Apache Sling Logging Logger Configuration to open it. The logs for Apache
Sling Logging Logger Configuration opens, as shown:
5. On the Log Level drop-down menu (where INFO is the default), select DEBUG, as shown:
Introduction
Adobe Experience Manager (AEM) architecture consists of frameworks such as Open Services Gateway
Initiative (OSGi) and Apache Sling. OSGi defines a dynamic component written in Java. The OSGi
specifications enable a development model where dynamic application comprises reusable components.
• Services: Connects bundles in a dynamic way by offering a publish-find-bind model for plain old
Java objects
• Life Cycle: Is the API to install, start, stop, update, and uninstall bundles
• Execution Environment: Defines the methods and classes are available in a specific platform
Bundles are built on Java’s existing standard way of packaging classes and resources together—the
JAR file (.jar). An OSGi bundle is just a JAR file with additional metadata added to the manifest file.
The OSGi metadata is provided as header information in the META- INF/MANIFEST.MF file. The
additional information consists of:
• Bundle name(s):
• Bundle version
o Copyright statement
o Contact address
Life Cycle
A life cycle layer adds bundles that can be dynamically installed, started, stopped, updated and
uninstalled. Bundles rely on the module layer for class loading, but add an API to manage the
modules in run time. The life cycle layer introduces dynamics that are generally not part of an
application. Extensive dependency mechanisms are used to assure the correct operation of the
environment. Life cycle operations are fully protected with the security architecture.
Modularity is at the core of the OSGi specifications and is embodied in the bundle concept.
Modularity is about keeping things local and not sharing. You should be familiar with the term
bundle in Java, which means a JAR file. In Java bundle, the contents of the JAR are completely
visible to all the other JARs. In OSGi bundle, the contents of JAR are hidden unless they are
explicitly exported. If a OSGi bundle wants to use another JAR, it must explicitly import the parts it
needs. Therefore, there is no sharing of the JAR.
Although the code hiding and explicit sharing provides many benefits, such as allowing multiple
versions of the same library being used in a single VM, the code sharing is there only to support
OSGi services model. The OSGi services model is about bundles that collaborate.
Services
Each service registration has a set of standard and custom properties. An expressive filter language
is available to select only the services in which you are interested. Properties can be used to find
the proper service or can play other roles at the application level.
Services are dynamic. This means a bundle can decide to withdraw its service from the registry
while other bundles are still using this service. Bundles using such a service must then ensure they
no longer use the service object and drop any references. OSGi applications do not require a
specific start ordering in their bundles.
The following steps show how the lookup is managed for dynamic services.
1. Examine the existing service.
In OSGi-based systems, functionality is mainly provided through services. Services implement one
or more interfaces, which define the type of service provided. It is the life cycle of the bundle that
defines the life cycle of the service. A service object may be instantiated when the bundle is started,
and is automatically removed when the bundle is stopped.
The advantages of OSGi services are:
• Lightweight services
Declarative services are a part of the OSGi container and simplify the creation of components that
publish and/or reference OSGi Services.
Features of Declarative Services:
• No need to write explicit code to publish or consume services.
• The service implementation class is not loaded or instantiated until the service is requested by a
client.
• Components have their own life cycle, bounded by the life cycle of the bundle, in which they are
defined.
Components are declared by using XML configuration files contained in the respective bundle, and
listed in the
Service-Component bundle manifest header. Declarative services resolve the bundle through XML
configuration files. You may handwrite and register these configuration files.
Declarative services are a good alternative to:
• Writing an activator
The OSGi Service Component (Declarative Services) reads the descriptions from started bundles.
The descriptions are in the form of XML files, which define the set of components for a bundle. It is
through the XML configuration definition information that the container:
• Registers the bundle’s services
• Real World: The OSGi framework is dynamic and is a perfect match for many real-world
scenarios. Applications can reuse the powerful primitives of the service registry in their own
domain. This reduces the time for writing code and provides global visibility, debugging tools, and
more functionality.
• Easy Deployment: The OSGi technology specifies how components are installed and managed.
Therefore, it is easy to deploy and integrate OSGi technology in the existing and future systems.
• Dynamic Updates: The OSGi component model is a dynamic model. You can install, start, stop,
update, and uninstall bundles without bringing down the whole system.
• Adaptive: The dynamic service model of OSGi enables bundles to find out what capabilities are
available on the system and adapt the functionality they can provide. This makes code more
flexible and resilient to changes.
• Transparency: The management API provides access to the internal state of a bundle as well as
how it is connected to other bundles. For example, most frameworks provide a command shell
that shows this internal state. You can stop parts of the applications to debug a certain problem or
bring in diagnostic bundles. OSGi applications can often be debugged with a live command shell.
• Versioning: In the OSGi environment, all bundles are carefully versioned. Only the bundles that
can collaborate are wired together in the same class space. This enables various bundles to
function with their own library.
• Simple: Easy-to-use annotations inform the runtime how a class wants to use the dynamics,
configuration, and dependencies on other services. The default configurations completely hide the
dynamics and OSGi. This simple model enables the gradual use of more advanced features.
• Small: The OSGi Release 4 Framework can be implemented in about a 300KB JAR file. Therefore,
OSGi can be used on a large range of devices—from very small to small to mainframes.
Components
A component can publish itself as a service and/or can have dependencies on other components and
services. The OSGi container will activate a component only when all the required dependencies are
met or available. Each component has an implementation class, and can optionally implement a public
interface providing this service.
A service can be consumed or used by components and other services. Basically, a bundle needs the
following to become a component:
• An XML file, where you describe the service the bundle provides and the dependencies of other
services of the OSGi framework
• A manifest file header entry to declare that the bundle behaves as a component
• The activate and deactivate methods in the implementation class (or bind and unbind methods)
• Service Component Runtime (SCR). A service of the OSGi framework to manage these
components.
As a best practice, always upload the bundle using JCR. That way, the release engineers and system
administrators have one common mechanism for managing bundles and configurations.
• Deactivate
• Modified
• Reference
@Component
The @Component annotation enables the OSGi Declarative Services to register your component. This is
the only required annotation for an OSGi component.
This annotation is used to declare the <component> element of the component declaration. The
required
<implementation> element is automatically generated with the fully qualified name of the class
containing the component annotation.
package com.adobe.osgitraining.impl;
import org.osgi.service.component.annotations.Component;
@Component
With OSGi DS annotations, type and property definitions are not done using annotations, as they
are with Felix SCR annotations, but through component modifiers (or attributes).
In fact, what we’re doing when creating a component is to register the type of service (by
implementing one or several interfaces) and to declare the properties made available by metatype
generation, all this with the same annotation.
Some of the attributes you can use with the @Component annotation are:
• service: Types under which to register this component as a service
Example:
@Component (service=WorkflowProcess.class,
1.1.1.1.1.1 name=”My Custom Workflow",
1.1.1.1.1.2 property={“description=Workflow process to set approval status”,
“process.label=Approval Status Writer”})
1.1.1.1.1.3
When creating a Sling servlet, the servlet properties are defined in the property component
modifier like in this example:
@Component (service=Servlet.class,
name=”My Custom Sling Servlet",
property={“sling.servlet.extensions=html”,
“sling.servlet.selectors=foo”,
“sling.servlet.paths=/bin/foo”,
“sling.servlet.methods=get”,
“sling.servlet.resourceTypes=project/components/mycomponent”,
})
Methods annotated with these annotations specify what happens when the component is
respectively activated, deactivated or its configuration is modified.
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
@Component
public class MyComponent{
@Deactivate
protected void deactivate() {
// do something
}
@Modified
protected void readConfig() {
// get values
}
}
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
@AttributeDefinition(
name=“Enter a String”,
description=“Your description”,
type=AttributeType.STRING
)
import org.osgi.service.component.annontations.Component;
import org.osgi.service.metatype.annotations.Designate;
@Component
@Designate(ocd=MyConfigInterface.class, factory=true)
private myString
@Activate
myString = config.myconfig_property()
}
}
2. Specify the Workspace as C:\Workspace and click Launch. The Workspace opens.
NOTE: To activate the code inside the bundle, you need to implement the
org.osgi.framework.BundleActivtor interface.
1. package com.adobe.training.core;
2.
3. import org.osgi.service.component.annotations.Activate;
4. import org.osgi.service.component.annotations.Component;
5. import org.osgi.service.component.annotations.Deactivate;
6.
7. import org.slf4j.Logger;
8. import org.slf4j.LoggerFactory;
9.
10. @Component
11.
12. public class Activator {
13. private final Logger logger = LoggerFactory.getLogger(getClass());
14.
15. @Activate
16. public void startBundle() {
17. logger.info("##################Bundle Started##################");
18. }
19. @Deactivate
20. public void stopBundle() {
21. logger.info("##################Bundle Stopped##################");
22. } }
1. In Project Explorer, right-click training.core, and select Run As > Maven install. The build starts.
5. Scroll down to the bottom of the file, and observe the log messages that indicate that
the bundle is started, as shown:
1. package com.adobe.training.core.services.impl;
2.
3. import org.osgi.service.component.ComponentContext;
4. import org.osgi.service.component.annotations.Activate;
5. import org.osgi.service.component.annotations.Component;
6. import org.osgi.service.component.annotations.Deactivate;
7. import org.osgi.service.component.annotations.Modified;
8. import org.slf4j.Logger;
9. import org.slf4j.LoggerFactory;
10.
1. In Project Explorer, right-click training.core and select Run As > Maven install. The
build starts.
This indicates that the class was successfully installed in the OSGI.
NOTE: With HTL, you can consume an OSGi service. Here, you are consuming the DeveloperInfo
service. After the service is is called, you can use the method from the service.
NOTE: The Eclipse AEM server with automatically sync the HTL file after it is saved. Make sure you
have your Eclipse AEM server started otherwise the file will not sync with the JCR.
12. If your changes are missing, you can force an update with full redeploy to the JCR by
right-clicking training.ui.apps and selecting Run AS > Maven Install
1. Log in to AEM, and click Adobe Experience Manager in the upper-left corner.
1. package com.adobe.training.core.services.impl;
2.
3. import org.osgi.service.component.annotations.Activate;
4. import org.osgi.service.component.annotations.Component;
5. import org.osgi.service.component.annotations.Deactivate;
6. import org.osgi.service.component.annotations.Modified;
7. import org.osgi.service.metatype.annotations.Designate;
8.
9. import org.slf4j.Logger;
10. import org.slf4j.LoggerFactory;
11.
5. Examine the various methods used in the class such as activate(), deactivate() and
getDeveloperInfo() to understand the logic behind them.
Notice the activate method takes a special class called DeveloperInfoConfiguration. This is a custom
6. In Eclipse Project Explorer, right click on com.adobe.training.core and choose New >
Class.
• Package: com.adobe.training.core.services
• Name: DeveloperInfoConfiguration
8. Click Finish.
1. package com.adobe.training.core.services;
2.
3. import org.osgi.service.metatype.annotations.AttributeDefinition;
4. import org.osgi.service.metatype.annotations.ObjectClassDefinition;
5. import org.osgi.service.metatype.annotations.AttributeType;
6. import org.osgi.service.metatype.annotations.Option;
7.
8. @ObjectClassDefinition(name = "Developer Info Service")
NOTE: You get the configurations in the activate() method by using the methods defined
in the DeveloperInfoConfiguration class.
1. In Project Explorer, right-click training.core, and select Run As > Maven install. The build starts.
3. Click Develop Info Service. The Developer Info Service opens, as shown:
7. Select TrainingProject Site > English > Edit (e) to open the page in a new tab in your browser.
https://www.osgi.org/developer/architecture/
http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
https://blog.osoco.de/2015/08/osgi-components-simply-simple-part-i/
Introduction
Apache sling is an open source web application framework that makes it easy to develop content-oriented
applications. Apache sling:
• Is powered by OSGi
Apache sling applications are a set of OSGi bundles that use the OSGi core and compendium services. The
Apache Felix OSGi framework and console provide a dynamic runtime environment, in which the code
and content bundles can be loaded, unloaded, and reconfigured at runtime.
In Apache Sling, a request URL is first resolved to a resource. Based on this resource, as well as the request
method and more properties of the request URL, a script or servlet is then selected to handle the request.
Objectives
• Resource Type - Each resource has a resource type that is used by the Servlet and Script resolver
to find the appropriate Servlet or Script to handle the request for the Resource.
When a request URL comes in, it is first resolved to a resource. Then, based on the resource, it selects the
servlet or script to handle the request.
Each content item in the JCR repository is exposed as an HTTP resource, so the request URL
addresses the data to be processed, not the procedure that does the processing. After the
content is determined, the script or servlet to be used to handle the request is determined in
cascading resolution that checks in the order of the priority as follows:
1. Properties of the content item itself
2. The HTTP method used to make the request
3. A simple naming convention within the URL that provides secondary information
For every URL request, the following steps are performed to get it resolved:
1. Decompose the URL
Processing is done based on the URL requests submitted by the user. The elements of the
URL are extracted from the request to locate and access the appropriate script.
Example - URL: http://myhost/tools/spy.printable.a4.html/a/b?x=12
The above URL can be decomposed into the following components:
After the URL is decomposed, the content node is located from the content path. This node is
identified as the resource, and performs the following steps to map to the request.
Consider the URL request: http://myhost/tools/spy.html
• Sling checks whether a node exists at the location specified in the request.
In the above example, it searches for the node spy.html.
• If no node is found at that location, the extension is dropped and the search is repeated. For
example, it searches for the node spy.
• If no node is found, then Sling returns the http code 404 (Not Found).
All scripts are stored in either the /apps or /libs folder, and are searched in the same order. If
no matching script is found in either of the folders, then the default script is rendered. When
the resource is identified from the URL, its resource type property is located and the value is
extracted. This value is either an absolute or a relative path that points to the location of the
script to be used for rendering the content.
For multiple matches of the script, the script with the best match is selected. The more the
selector matches, the better.
Example of rendering the content:
Super types are also taken into consideration when trying to locate a script. The advantage of
resource super types is that they may form a hierarchy of resources where the default
resource type sling/servlet/default (used by the default servlets) is effectively the root.
The resource super type of a resource may be defined in two ways:
Extend and Customize Adobe Experience Manager 174
1. sling:resourceSuperType property of the resource.
The Resource Resolver is a part of Sling that resolves incoming requests to actual or virtual
resources. For example, a request for /training/english will be resolved to a corresponding
JCR node. However, if you do not want to expose the internal JCR structure, or if it cannot be
resolved to a JCR node, you can define a set of resolver rules through the Web Console. You
can also use the standard OSGi configuration mechanisms in the CRXDE Lite to define a set
of resolver rules.
The Resource Resolver abstracts:
• The path resolution
Resource mapping is used to define redirects, vanity URLs, and virtual hosts. You can access
the Resolver Map entries through the Resource Resolver tab of the Web Console. You can
access the console with this link: http://localhost:4502/system/console/jcrresolver
The following node types help with the definition of redirects and aliases.
sling:ResourceAlias Mixin node type defines the sling:alias property, and may be attached to any
node, which does not otherwise allow the setting of a property named
sling:alias.
Properties Description
sling:match Defines a partial regular expression used on a node’s name to match the
incoming request.
sling:internalredirect Causes the current path to be modified internally to continue with resource
resolution
Each entry in the mapping table is a regular expression, which is constructed from the
resource path below /etc/map. The following rules apply:
• If any resource along the path has a sling:match property, the respective value is used in the
corresponding segment instead of the resource name.
• Only resources having a sling:redirect or sling:internalRedirect property are used as table entries.
Other resources in the tree are just used to build the mapping structure.
http/www.example.com.80 /example yes Prefixes the URI paths of the requests sent to
this domain with the string /example
http/localhost.\d* /content yes Prefixes the URI paths with /content for
requests to localhost, regardless of actual port
the request was received on. This entry only
applies if the URI path does not start with
http/localhost.\d*/cgi-bin /scripts yes Replaces the /cgi-bin prefix in the URI path
with /scripts for requests to localhost, regardless
of actual port the request was received on.
http/localhost.\d*/gateway http://gbiv.com yes Replaces the /gateway prefix in the URI path
with http://gbiv.com for requests to localhost,
regardless of actual port the request was
received on.
• JSON
• docview.xml
• sysview.xml
• html
You can use the Configuration tab of the Web Console to configure the GET servlet, as
shown:
NOTE: This code will work only if the com.adobe.granite.csrf.impl.CSRFFilter filter is defined in OSGi
configurations.
The above code will set the title and text properties on a node in the location /mycontent. If
this node does not exist, it will be created. Otherwise, the existing content at that URL would
be modified.
You can perform a similar operation using the following cURL commands:
1. Launch Eclipse by double-clicking the Eclipse shortcut on the desktop. The Eclipse Launcher
2. Specify the Workspace as C:\Workspace and click Launch. The Workspace opens.
1. package com.adobe.training.core.servlets;
2.
3. import java.io.IOException;
4.
5. import javax.servlet.Servlet;
6. import javax.servlet.ServletException;
7. import org.apache.sling.api.SlingHttpServletRequest;
8. import org.apache.sling.api.SlingHttpServletResponse;
9. import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
10.
11. import org.osgi.service.component.annotations.Component;
12.
13. @Component( service = Servlet.class,
14. name="TrainingTitleServlet",
15. property = {
16. "sling.servlet.paths=/bin/trainingproject/titleservlet",
17. "sling.servlet.extensions=html"
18. })
19.
20. //TitleSlingServlet uses resourceTypes and extensions to bind to URLs
21.
7. In Project Explorer, right-click training.core and select Run As > Maven install. The
build starts.
3. Right-click training.core, and select Run As > Maven install to build the project. The
project is built.
2. Verify that the command to create a page ran successfully by checking for the status
Created, as shown:
8. Click Edit (e). The Sling cURL page opens in a new tab.
11. Verify that the command to add content to the page ran successfully by checking for
the status i_am_a_new_text, as shown:
14. Verify that the command to unlock the page ran successfully by checking for the status,
Page unlocked, as shown:
17. Verify that the command to activate the page ran successfully by checking for the status,
Replication Started, as shown:
Problem
To access the data storage in the Resource Tree and/or JCR, authentication is required to properly set up
access control and guard sensitive data from unauthorized access. For regular request processing, this
authentication step is handled by the Sling Authentication subsystem.
• Allow services access to ResourceResolvers and/or JCR Sessions without requiring to hard-code or
configure passwords.
• Allow services to use service users that are specially configured for service level access (usually
done on unix systems).
Concept of Service
A service is a piece or collection of functionality. The examples of services are the Sling queuing system,
Tenant Administration, or a Message Transfer System. Each service is identified by a unique service
name. Because a service is implemented in an OSGi bundle or a collection of OSGi bundles, services are
named by the bundles providing them.
A service may be comprised of multiple parts, so each part of the service may be further identified by a
subservice name. This subservice name is optional though. The examples of subservice name are the
names for subsystems in a Message Transfer System, such as accepting messages, queueing messages,
and delivering messages.
The combination of the Service Name and Subservice Name defines the Service ID. The Service ID is finally
mapped to a Resource Resolver and/or JCR user ID for authentication.
Therefore, the actual service identification (service ID) is defined as:
service-id = service-name [ ":" subservice-name ].
The service-name is the symbolic name of the bundle providing the service.
The implementation in Apache sling of the service authentication concept described above consists of
three parts: ServiceUserMapper, ResourceResolverFactory, and SlingRepository.
ServiceUserMapper
The ServiceUserMapper service allows for the mapping Service IDs comprised of the Service Names
defined by the providing bundles and optional Subservice Name to ResourceResolver and/or JCR
Repository user IDs. This mapping is configurable such that system administrators are in full control of
assigning users to services.
The ServiceUserMapper defines the following API:
ResourceResolverFactory
The second part is support for service access to the Resource Tree. The ResourceResolverFactory service
is enhanced with a new factory method, as shown below:
This method allows for access to the resource tree for services where the service bundle is the bundle
actually using the ResourceResolverFactory service. The optional Subservice Name may be provided as
an entry in the authenticationInfo map.
In addition to having new API on the ResourceResolverFactory service to be used by services, the
ResourceProviderFactory service is updated with support for Service Authentication.
SlingRepository
The third part is an extension to the SlingRepositoryservice interface to support JCR Repository access for
services:
This method allows for access to the JCR Repository for services, where the service bundle is the bundle
actually using the SlingRepository service. The additional Subservice Name may be provided with the
subServiceName parameter.
Consequently, these methods are being deprecated and will be removed in future releases of the service
implementations.
• ResourceResolverFactory.getAdministrativeResourceResolver
• SlingRepository.loginAdministrative
The implementations in Sling's bundle will remain implemented in the near future. However, there will be a
configuration switch to disable support for these methods: If the method is disabled, a LoginException is
always thrown from these methods. The JavaDoc of the methods is extended with this information.
5. Click the green checkmark in the lower-right corner of the dialog box.
10. On the left, search for training-user by using the search option, as shown:
In this task, you will create the mapping from our bundle to the user with an OSGi configuration
node. The configuration we are going to setup is the ServiceUserMapperImpl.
• Name: org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-
training
• Name=user.mapping, type=String,
value=com.adobe.training.core:training=training-user
The user.mapping allows us to map a bundle with a subservice name to a service user, as shown:
6. In Eclipse, go to training.ui.apps.
8. Accept the default values and click Finish. The changes are imported from server, as
shown:
Introduction
Sling Models provide excellent support for web content authors to build pages in Adobe Experience
Manager (AEM) and to easily customize the pages in AEM to their requirements. Sling Models let AEM
developers access Sling content without creating their own adapters. Thus avoiding a large amount of
Objectives
• Describe ResourceResolver
The ResourceResolver interface defines two kinds of methods to access resources—the resolve
method and the getResource method. The difference lies in the algorithm applied to find the
requested resource, and in the behavior in case a resource cannot be found.
Lifecycle
A Resource Resolver has a life cycle which begins with the creation of the Resource Resolver using
any of the factory methods and ends with calling the close() method. It is very important to call the
close() method after the resource resolver is not used anymore to ensure the system resources are
properly cleaned up.
To check whether a Resource Resolver can still be used, the isLive() method can be used.
An adapter design pattern is used when you want two different classes with incompatible
interfaces to work together. Sling offers an adapter pattern to conveniently translate objects that
implement the Adaptable interface. This interface provides a generic adaptTo() method that will
translate the object to the class type being passed as the argument.
The Resource and Resource Resolver interfaces are defined with a method adaptTo()which adapts
the object to other classes. The adaptTo pattern is used to adapt two different interfaces (for
example, resource to node).
Node node = resource.adaptTo(Node.class)
Using this mechanism, the JCR session of the Resource Resolver calls the adaptTo method with the
• A combination of both
A Sling Model is a Java class located in an OSGi bundle that is annotated with @Model and
In the example below, data members (the fields of the Java class) are annotated with @inject
to map to node properties.
• Allows you to adapt multiple objects—minimal required are Resource and SlingHttpServletRequest
• Works with existing Sling infrastructure (for example, changes to other bundles are not required)
• Provides the ability to mock dependencies with tools like Mockito @InjectMocks
4. @Inject
5. private String propertyName;
In this case, a property named propertyName will be looked up from the Resource (after first
adapting it to a ValueMap) and will be injected.
For an interface, it is similar:
1. @Model(adaptables=Resource.class)
2. public interface MyModel {
4. @Inject
5. String getPropertyName();
6. }
Client code does not need to be aware that Sling Models is being used. It just uses the Sling
Adapter framework:
MyModel model = resource.adaptTo(MyModel.class)
4. @Inject @Named("secondPropertyName")
5. private String otherName;
6. }
The following table shows the different types of Sling Model annotations and its usage:
@Inject @Inject private String propertyName; (class) A property named propertyName will
@Inject String getPropertyName(); (interface) be looked up from the Resource
(after first adapting it to a ValueMap)
and it is injected. If property is not
@Default @Inject @Default(values=”AEM”) private A default value (for Strings, Arrays &
String technology; primitives)
@Named @Inject @Named(“title”) private String Inject a property whose name does
page Title; not match the Model field name.
• More robust (in case of name collisions among the different injectors, you must ensure the
The following annotations are provided, which are tied to specific injectors:
Debugging
In order to see logging specific to Sling Models, add a logger for the package
org.apache.sling.models, set the log level to TRACE and dump the messages in to appropriate log
file.
1. In CRXDE Lite, right-click content and select Create > Create Node. The Create Node dialog box
opens.
2. In the Create Node dialog box, carry out the following functions, as shown:
5. Create a child node under stocks, carry out the following functions:
6. Click OK and select Save All to save the changes. The node ADBE is created.
1. Launch Eclipse by double-clicking the Eclipse shortcut on the desktop. The Eclipse Launcher
opens.
2. Specify the Workspace as C:\Workspace and click Launch. The Eclipse Workspace opens.
NOTE: This StockModel will work with the StockDataImporter that you will create later in
this course. Because this data importer is not yet created, you will use a servlet and dummy
data to simulate the input and output for the StockModel.
1. package com.adobe.training.core.servlets;
2.
3. import java.io.IOException;
4.
5. import javax.servlet.Servlet;
6. import javax.servlet.ServletException;
7.
8. import org.osgi.service.component.annotations.Component;
10. Right-click training.core, and perform Run As > Maven install to build the project. The project is
built.
http://localhost:4502/content/trainingproject/en.model.html/content/stocks/ADBE
13. Verify the message returned by the model is displayed in the browser, as shown:
In this task you will adapt the request rather than the resource to get the same outcome.
1. package com.adobe.training.core.models;
2.
3. import org.apache.sling.api.SlingHttpServletRequest;
4. import org.apache.sling.api.resource.Resource;
5. import org.apache.sling.api.resource.ValueMap;
6. import org.apache.sling.models.annotations.DefaultInjectionStrategy;
7. import org.apache.sling.models.annotations.Model;
8. import org.apache.sling.models.annotations.injectorspecific.ResourcePath;
9. import org.apache.sling.models.annotations.injectorspecific.Self;
10.
11. import javax.annotation.PostConstruct;
12.
13. /**
14. * This model represents an IEX api stock data structure created from the StockDataImporter:
15. * /content/stocks/
16. * + <STOCK_SYMBOL> [sling:OrderedFolder]
17. * + lastTrade [nt:unstructured]
18. * - companyName = <value>
19. * - sector = <value>
20. * - lastTrade = <value>
21. * - ..
22. */
23.
24. @Model(adaptables=SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
25. public class StockModelAdaptFromRequest {
26.
27. @Self
28. private SlingHttpServletRequest request;
29.
30. @ResourcePath(path = "/")
1. package com.adobe.training.core.servlets;
2.
3. import java.io.IOException;
4.
5. import javax.servlet.Servlet;
6. import javax.servlet.ServletException;
6. Right-click training.core, and perform Run As > Maven install to build the project. The build starts.
http://localhost:4502/content/trainingproject/en.model.html/content/stocks/ADBE
9. Verify the message returned by the model is displayed in the browser, as shown:
NOTE: Notice that you can adapt the request rather than the resource to our StockModel. The object
you are adapting does not matter as long as the Sling Model is built to handle the object
The Sling Model Exporter feature allows new annotations to be added to Sling Models that define how the
Model can be exported as a different Java object, or more commonly, serialized into a different format
such as JSON, to be consumed by your front-end application (headless CMSs for example).
This feature is not available OOTB with the WCMUsePojo API (for which you would have to override the
activate() method), whereas with Sling Models the initialization is done by a method annotated with
@PostConstruct.
The snippet below shows the declaration of a model for an AEM component, that gets exported with the
Jackson exporter using the specific component adapter interface
com.adobe.cq.export.json.ComponentExporter:
@Model(adaptables=SlingHttpServletRequest.class,
adapters= {ComponentExporter.class},
resourceType="trainingproject/components/content/trainingtitle",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
1. From CRXDE Lite, click the Package icon. The CRX Package Manager page is displayed.
2. Click Upload Package, as shown. The Upload Package dialog box opens.
4. Click OK.
5. Verify the uploaded package is now available in CRX Package Manager, as shown:
11. Right-click com.adobe.training.core.models and paste the file. The TrainingTitle.java class is created, as
shown:
1. package com.adobe.training.core.models;
2.
3. import javax.annotation.PostConstruct;
4. import javax.inject.Inject;
5. import javax.inject.Named;
6.
7. import org.apache.sling.api.SlingHttpServletRequest;
8. import org.apache.sling.models.annotations.*;
9. import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
10. import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
13. Right-click training.core, and perform Run As > Maven install to build the project. The build starts.
16. Navigate to Sites > TrainingProject Site, and click the thumbnail on English and select the page, as
shown:
17. Click Edit (e). The page opens in a new tab for editing.
http://localhost:4502/content/trainingproject/en/jcr:content/root/responsivegrid/trainingtitle.model.json,
as shown:
• SQL
• SQL-2
Internally, the query engine uses a cost-based query optimizer that asks all the available query indexes for
the estimated cost to process the query. It then uses the index with the lowest cost.
By default, the following indexes are available:
• Property index for each indexed property
• Node type index, which is based on an property index for the properties jcr:primaryType and
jcr:mixins
If no index can efficiently process the filter condition, the nodes in the repository are traversed at
the given subtree. Usually, data is read from the index and repository while traversing over the
query result. There are exceptions, however, where all the data is read in memory when using a
full-text index and when using an order by clause.
Native Queries
To take advantage of features available in full-text index implementations, such as Apache Lucene
and Apache Lucene Solr, the so-called native constraints are supported by Oak. These constraints
are passed directly to the full-text index. The
full-text index is supported for both XPath and SQL-2. For XPath queries, the name of the function
is rep:native, and for SQL-2, it is native.
The first parameter is the index type and currently supported parameters are Solr and Lucene. The
second parameter is the native search query expression.
For SQL-2, the selector name (if needed) is the first parameter, just before the language. If full-text
implementation is not available, the queries will fail.
4. Click OK then set the following properties for the new node:
A full-text indexer based on Apache Lucene is available in AEM. If a full-text index is configured, then all the
queries with a full-text condition use the full-text index, no matter if there are other conditions that are
indexed and there is a path restriction.
If no full-text index is configured, then queries with full-text conditions may not work as expected. The query
engine has a basic verification in place for full-text conditions, but it does not support all the features that
Lucene does, and it traverses all the nodes if there are no indexed constraints.
As the index is updated through an asynchronous background thread, some full-text searches will be
unavailable for a small window of time until the background processes are finished.
2. Name the node LuceneIndex and set the node type to oak:QueryIndexDefinition.
You can use the Solr index for full-text search, as well as search by path, property restrictions, and primary
type restrictions.
• It can be used for any type of JCR query.
• It can be configured to work as an embedded server with the AEM instance, or as a remote server.
7. Click the Edit icon, and in the resulting dialog box, select the server type as Embedded Solr from
the drop-down list.
8. Click Save.
9. Search for Oak Solr embedded server configuration in the Web Console under OSGi >
Configuration.
10. Click the Edit icon in the Oak Solr embedded server configuration, and update the configuration.
The Solr home directory configuration will look for a folder with the same name in the AEM
installation folder.
When removing an index, it is always recommended to temporarily disable the index by setting
the type property to disabled and do testing to ensure that your application functions correctly
AEM also integrates two indexing tools present in AEM as part of the Adobe Consulting Services
Commons toolset.
• Explain Query: A tool designed to help administrators understand how queries are executed.
• Oak Index Manager: A Web User Interface for maintaining existing indexes.
• Detects slow queries and warns about queries that could be potentially slow
The Oak Index Manager is a simple Web UI created to facilitate index management, such as
maintaining indexes, viewing their status, or triggering re-indexes. You can use the UI to filter
indexes in the table by typing in the filter criteria in the search box in the upper-left corner of the
screen.
Query Syntax
As specified, JSR 170: SQL and XPath syntaxes have the same feature set. Since JSR-283, Abstract Query
Model (AQM) defines the structure and semantics of a query. The specification defines two language
bindings for AQM:
• JCR-SQL2 (Grammar: http://www.h2database.com/jcr/grammar.html)
• JCR-JQOM
A query has one or more selectors. When the query is evaluated, each selector independently selects a
subset of the nodes in the workspace based on Node type.
Join transforms the multiple sets of nodes selected by each selector into a single set. The join type can be
inner, left-outer, or right-outer.
AQM Concepts: Constraints
A query can specify a constraint to filter the set of node-tuples. The constraints may be any combination of:
• Absolute or relative path. For example, nodes that are children of /pictures
• Full-text search. For example, nodes that have a property containing the phrase beautiful sunset.
Search Basics
Defining and executing a JCR-level search requires the following logic:
QueryManager qm = session.getWorkspace().getQueryManager();
• Get the QueryManager for the Session/Workspace:
• Typically O(n), where n is the number of results, versus to the total number of nodes
• Sorting, limit/offset
Testing Queries
You can test your queries using CRXDE Lite. Access the Query Tool on the Tools menu from the top toolbar
in CRXDE Lite, as shown:
3. Right-click com.adobe.training.core.servlets and paste the file. The SearchServlet.java class is created,
as shown:
1. package com.adobe.training.core.servlets;
2.
3. import com.day.cq.wcm.api.PageManager;
4. import com.google.gson.Gson;
5. import org.apache.sling.api.SlingHttpServletRequest;
6. import org.apache.sling.api.SlingHttpServletResponse;
7. import org.apache.sling.api.resource.Resource;
8. import org.apache.sling.api.resource.ResourceResolver;
9. import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
10.
11. import org.osgi.service.component.annotations.Component;
12.
13. import javax.jcr.query.Query;
5. Right-click training.core, and perform Run As > Maven install to build the project. The build starts.
Introduction
With AEM, there’s different approaches that can be taken regarding event management. Depending on
the complexity, the nature of the payload or intensity of process, inherent requirements or business roles
• Events at the OSGi container level, with the OSGi Event Admin
• Events at the Sling level, with Sling Jobs (that can be scheduled) and the ResourceChangeListener
• Events at the level of AEM, with different high-level objects e.g. workflow process steps, polling
importers, replication actions, notifications or auditing (all based on Sling Jobs)
Objectives
e. Application-generated events
g. External events
i. An Event Handler, to listen to a certain topic and process the data carried by the event upon reception
Here’s an example of a component registering a listener. Notice the immediate modifier set to true,
this is required here because we need the component to listen to events upon activation. The
method handleEvent() enables to consume the event with the Event object passed through it.
// do something
Limitations
This distribution of OSGi events is a broadcast, which means that the same event is being
consumed by all the components that had registered listeners against the same topic. If no listener
has been registered on that topic, the event is lost, hence won’t be handled later (it doesn’t get
queued). We’ll see later in this module that this “fire and forget” behavior can be avoided with the
use of events managed as jobs with Sling.
1. Launch Eclipse by double-clicking the Eclipse shortcut on the desktop. The Eclipse Launcher
2. Specify the Workspace as C:\Workspace and click Launch. The Eclipse Workspace opens.
1. package com.adobe.training.core.listeners;
2.
3. import java.util.HashMap;
4.
5. import org.osgi.service.component.annotations.Component;
6. import org.osgi.service.component.annotations.Reference;
7. import org.osgi.framework.Constants;
8. import org.osgi.service.event.Event;
9. import org.osgi.service.event.EventHandler;
10. import org.osgi.service.event.EventConstants;
11. import org.slf4j.Logger;
12. import org.slf4j.LoggerFactory;
13. import com.day.cq.replication.ReplicationAction;
14. import com.day.cq.replication.ReplicationActionType;
15.
16. import org.apache.sling.event.jobs.JobManager;
17.
18. @Component( immediate = true,
19. service = EventHandler.class,
20. property = {Constants.SERVICE_DESCRIPTION + "=Replication Listener kicks off a job",
1. In Project Explorer, right-click training.core and choose Run As > Maven install. The build starts.
4. Click Edit (e) in the action bar. The English page opens.
5. Click the Page Information icon at the top left and select Publish Page. The Publish page appears
with All Assets and asset.jpg.
6. Click Publish at the top right and verify if the page is published, as shown:
9. Navigate to the AEM Web Console and Select OSGi > Events from the menu. The Events are listed.
d. event.topics=com/day/cq/replication
e. paths=/content/trainingproject/en
f. type=ACTIVATE
h. A job consumer, to process that job and remove it from the queue
Because of the unicity of the process, once a job consumer has processed the job it gets removed
from the queue and no other consumer would be able to process it (which is a case we should
avoid anyway). Similarly, if no job consumer is registered to process a given job topic, the job stays
in the queue (which is again something that would be considered a deployment error).
Adding a job consists of calling the method addJob() of the org.apache.sling.event.jobs.JobManager
service and passing to it a topic (a string identifying the job) and a HashMap to carry the job
information.
A component that needs to consume a job for processing must implement the interface
org.apache.sling.event.jobs.consumer.JobConsumer and override the process method to get the
Job object org.apache.sling.event.jobs.Job, like seen below:
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
@override
public JobResult process(final Job job) {
// do something
Monitoring
To view all registered topics with their statistics, go to the console under Sling > Jobs in the Web
console:
http://localhost:4502/system/console/slingevent
NOTE: This console only shows topics that have been processed by a Job consumer, therefore if a
job is added and never consumed, the corresponding topic won’t be visible. For debugging
purposes, custom jobs can be found in the repository under /var/eventing/jobs.
3. In Eclipse, right-click com.adobe.training.core and paste the file. The ReplicationLogger.java class is
created, as shown:
1. package com.adobe.training.core;
2.
3. import org.osgi.service.component.annotations.Component;
4. import org.osgi.service.component.annotations.Reference;
5. import org.apache.sling.api.resource.LoginException;
6. import org.apache.sling.api.resource.ResourceResolver;
7. import org.apache.sling.api.resource.ResourceResolverFactory;
8. import org.apache.sling.event.jobs.Job;
9. import org.apache.sling.event.jobs.consumer.JobConsumer;
10.
11. import org.slf4j.Logger;
12. import org.slf4j.LoggerFactory;
13. import com.day.cq.wcm.api.Page;
7. To publish (activate) a page, select the page in AEM, and select Quick Publish. The page is published.
9. You should see logged messages giving the titles of pages as they are activated, as shown:
11. Search for replicationjob using browser search. The Topic Statistics for replicationjob is returned.
@override
public void run() {
// do something
1. package com.adobe.training.core.schedulers;
2.
3. import org.apache.sling.api.resource.*;
4. import org.osgi.service.component.annotations.Component;
5. import org.osgi.service.component.annotations.Activate;
6. import org.osgi.service.component.annotations.Modified;
7. import org.osgi.service.component.annotations.Reference;
8. import org.osgi.service.metatype.annotations.AttributeDefinition;
9. import org.osgi.service.metatype.annotations.AttributeType;
10. import org.osgi.service.metatype.annotations.Designate;
11. import org.osgi.service.metatype.annotations.ObjectClassDefinition;
12.
13. import org.slf4j.Logger;
5. Right-click training.core, and select Run As > Maven install. The project is built.
Notice the defaults come from the java class we just created.
NOTE: Now you know the scheduler is running. However, you need to test to see if it will delete, or
cleanup /mypathtraining nodes.
10. In CRXDE Lite, right-click the root node (/), and select Create > Create Node named mypathtraining, as
shown:
12. Click Save All to save the changes and wait 30 seconds.
Notice the configuration has a + icon next to it. This means that it is a configuration factory, and you
can have multiple instances of this service.
NOTE: When you open the config, you will notice the PID is not set, but rather a Factory PID is
provided. This means that the actual PID is assigned when a configuration is made for this factory.
• Name: com.adobe.training.core.schedulers.CleanupScheduledTask-mycustompath
• Select sling:OsgiConfig from Type drop-down menu.
• Name: cleanupPath
Type: (String)
Value: /mycustompath
• Name: scheduler.expression
Type: (String)
Value: 0/30 * * * * ?
21. To test your configuration, right-click the root node (/), as shown and select Create > Create Node.
• Name: mycustompath
• Type: nt:unstructured
24. Wait 30 seconds and refresh CRXDE Lite. Observe the node is deleted.
a. /apps/trainingproject/config.author/com.adobe.training.core.schedulers.CleanupScheduledTask-
mysecondpath
3. Observe how both the paths are not being cleaned up.
Introduced with Sling 9 (2017), its goal is to provide an observation mechanism, similar to the JCR
Then resource changes can be caught by overriding the method onChange() as seen in this example:
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
// do something
For these reasons, listening to only resource-related events will be preferably done using the
ResourceChangeListener, for performance considerations.
1. package com.adobe.training.core.listeners;
2.
3. import org.apache.sling.api.resource.*;
4. import org.osgi.service.component.annotations.Component;
5. import org.osgi.service.component.annotations.Reference;
6.
7. import org.apache.sling.api.resource.observation.ResourceChange;
8. import org.apache.sling.api.resource.observation.ResourceChangeListener;
9.
10. import java.util.HashMap;
12. Click to the Page information icon > Open Properties. The Page Properties window (with the name
Test!) opens.
http://localhost:4502/system/console/slingevent
Introduction
APIs are at the highest layer of the Adobe Experience Manager (AEM) architecture stack, and are most
closely related to various business tasks a typical content producer would create in AEM. You can use APIs
in AEM to develop a custom data importer service that helps import data from a site.
Objectives
• The auto-blogging feature, which automatically creates blog posts from an external RSS or Atom
feed
• iCalendar subscriptions, which automatically creates calendar events from an external ICS file or
subscribes to or from other calendars
1. Double-click the Eclipse shortcut on the desktop. The Eclipse Launcher opens.
1. In Project Explorer, right-click training.core and choose Run As > Maven install. The build starts.
Name: interval
Type: String
Value: 300
Name: source
Type: String
Value: stock:ADBE
Name: target
Type: String
8. Click Mixins in the toolbar at the top, click +, and select cq:PollConfig from the drop-down menu, as
shown:
10. Click Save All to save the properties created on the adobe_stock node.
NOTE: The configurations you created will provide the information to the custom polling importer
you created, StockDataImporter.java class. As a result, in 300 seconds (5 minutes), you should see a
new node created at the target path (/content) provided in the node.
11. Refresh /content in CRXDE Lite, and notice that there is a ADBE node created.
AEM has high-level APIs that you can use to create pages based on the underlying data structures.
Assets consist of nodes and properties along with a sling:resourceType. You can use the
com.day.cq.dam.api.AssetManager to create the asset, and the com.day.cq.tagging.TagManager
APIs to tag the assets. Using these APIs, you can create assets, tag them, as well as add metadata to
the assets.
You can use this process for migration by pointing to the existing assets and creating the asset in a
Digital Asset Manager, with all the asset information that is required.
Based on the complexity and size of the migrating system, you can use any of the following three
methods for migration:
• Manual migration (human entry): Hire emplyees to enter the data into a format that is compatible
with AEM.
• Automated migration (using APIs): Export data as XML from the legacy system, write a script to
convert the data into a JCR-friendly XML, and import that package into JCR.
Hybrid migration (a combination of manual and automated): Import the bulk of the data through
XML, and hire emplyees to update the data manually. For example, you can follow this method to
add metadata to modify the data.
1. Double-click the Eclipse shortcut on the desktop. The Eclipse Launcher opens.
5. In Eclipse, right-click com.adobe.training.core.servlets, and paste the file. The PageCreator.java class is
created, as shown:
1. package com.adobe.training.core.servlets;
2.
3. import java.io.IOException;
4. import java.util.HashMap;
5.
6. import javax.jcr.Session;
7. import javax.servlet.Servlet;
8. import javax.servlet.ServletException;
9.
10. import com.google.gson.Gson;
11. import org.osgi.service.component.annotations.Component;
12. import org.osgi.service.component.annotations.Reference;
13.
14. import org.apache.sling.api.SlingHttpServletRequest;
15. import org.apache.sling.api.SlingHttpServletResponse;
16. import org.apache.sling.api.resource.Resource;
17. import org.apache.sling.api.servlets.SlingAllMethodsServlet;
18.
19. import org.slf4j.Logger;
20. import org.slf4j.LoggerFactory;
21.
22. import com.day.cq.replication.ReplicationActionType;
23. import com.day.cq.replication.Replicator;
24. import com.day.cq.tagging.Tag;
25. import com.day.cq.tagging.TagManager;
26. import com.day.cq.wcm.api.Page;
27. import com.day.cq.wcm.api.PageManager;
28.
29. /**
1. In Project Explorer, right-click training.core and choose Run As > Maven install. The build starts.
4. Right-click content, and select Create > Create node. Provide the following values:
• Name: sling:resourceType
• Type: String
• Value: trainingproject/tools/pagecreator
NOTE: You have content that you can post and a servlet that will be triggered. You can now test with
a cURL command.
10. Open your command terminal, and run the following command:
NOTE: If you are on a Mac, you can format the returned json by adding | json_pp.
1. Double-click the Eclipse shortcut on the desktop. The Eclipse Launcher opens.
2. Specify the Workspace as C:\Workspace and click Launch. The Eclipse Workspace opens.
1. In Project Explorer, right-click training.core and select Run As > Maven install. The build starts
4. Open your command terminal, and type the location of CSV files, as follows:
CD C:\Exercise_Files\12_Deep_Dive_into_AEM_APIs
6. Verify that all the pages are not created in AEM: Sites > TrainingProject Site > click the thumbnail on
English page, as shown:
NOTE: If you want to use the browser rather than cURL, you can install the http-pagecreator.zip content
package (from the exercise folder) and do a request for http://localhost:4502/content/pagecreator.csv.html.
AEM Projects comes with several out-of-the box (OOTB) project templates. When creating a new
project, authors can choose from these available templates. For large AEM implementations with
unique business requirements, developers can create custom project templates. With these custom
templates, developers can configure the project dashboard, hook into custom workflows, and
create additional business roles for a project.
You should create project templates under source control, and they should be beneath your
• Roles - There are three default roles for every project: Observers, Editors, and Owners. By adding child
nodes beneath the roles node, you can add additional business specific project roles for the template.
You can then tie these roles to specific workflows associated with the project.
• Workflows - Workflows enable you to automate AEM activities. Workflows consist of a series of steps
that are executed in a specific order. Each step performs a distinct activity, such as activating a page or
sending an email message. One of the reasons for creating a custom project template is that it gives
you the ability to configure the available workflows for the project. These can be OOTB workflows or
custom workflows. Beneath the workflows node there needs to be a models node (nt:unstructured)
and a child node to specify the available workflow models.
The root node of the project template will be of type cq:Template. On this node, you can configure
the jcr:title and jcr:description properties that will be displayed in the Create Project wizard. There
is also a property called wizard that points to a form that will populate the properties of the
project.
2. In the Projects console, click Create > Project. The Create Project page opens.
b. Enter Carlene Avery in the User field, ensure the dropdown beside it is set to Editors, and click
Add.
c. Enter Iris Mccoy in the User field, ensure the dropdown beside it is set to Observers, and click
Add.
• Workflow console
Depending on the type of workflow, the workflow goes through a series of steps until its completion.
Based on your business requirements, you can modify an existing workflow or create a new
one. You can use the Workflow console to manage workflow models and launchers. A
workflow model includes a Flow Start and a Flow End step. These steps indicate the
beginning and end of the workflow.
In AEM, there are a number of steps available for workflows, such as Participant, Process,
Create Task, Delete Node, Dialog Participant, Dynamic Participant, and Form Participant.
Each step can contain any number of actions and associated conditions. For example, a step
in a publish workflow may involve the step- approval from an editor. Two of the most
commonly used workflow steps are Participant and Process.
Participant Step
The Participant step requires manual intervention by a person to advance the workflow. It
enables you to assign a step to a user or a group of users. If the workflow is assigned to just
one user, that user needs to complete that task before the workflow can proceed to the next
step. If the workflow is assigned to a group of users, all those users need to complete the
task.
You can notify participants of their required action through email. Also, if configured, the
participants will receive an email notification when the workflow is completed or if the
workflow is terminated.
You can configure timeouts and timeout handlers for this step. Timeout is the period after
which the step will be timed out. You can select between off and immediate, and if you want
to specify specific blocks of time, you can select 1h, 6h, 12h, and 24h. The timeout handler
controls the workflow when the step times out.
Every new model created includes a sample participant step, which you can either edit or
remove. You can add and configure additional steps as required.
The Process step involves automatic actions that are executed by the system if specific conditions are
met. This step:
o Workflow control processes: Control the behavior of the workflow and do not perform any action on
content
WCM processes: Perform WCM-related tasks, such as activating a page or confirming registration
o Versioning processes: Perform version-related tasks, such as creating versions of the payload
o DAM processes: Perform DAM-related tasks, such as creating thumbnails, creating sub-assets, and
extracting metadata
o Collaboration processes: Are related to the collaboration features of AEM, such as the collabration
with social communities.
You can extend workflow steps with scripts to provide more functionality and control. You can create
customized process steps by using the following methods:
• Java class bundles: Create a bundle with the Java class, and then deploy the bundle into the OSGi
container by using the Web console.
• ECMA scripts: Scripts are located in JCR under etc/workflows, and they are executed from there. To
use a custom script, create a new script with the extension .ecma under the same folder. The script
will then show up in the process list for a process step.
Creating a Workflow
To create a workflow:
2. Double-click the newly created model, and modify the steps by clicking and dragging the required
workflow steps from the sidekick to the workflow.
The Workflow launcher enables you to invoke a workflow based on certain predefined conditions.
These conditions are based on changes to the content located in JCR. For example, when a page is
modified, it can trigger a workflow.
You can configure the workflow launchers through the Workflow console,
(http://localhost:4502/libs/cq/workflow/admin/console/content/launchers.html), as shown:
• Node type: nt:unstructured: Type of node that is affected by the workflowPath: /content/Geometrixx:
Property that indicates the path of the node
• Workflow: PublishPage: Property that indicates the workflow to be executed when the event occurs
• Activate: Enable: Property that controls whether the launcher should be activated
• Run mode (s): Author: Property that indicates the type of server to which the launcher applies
Easy to start or stop Requires the use of Web Console to stop the
listener component
The workflow model can be changed dynamically Requires programmatic or configuration changes
Involves more overhead, and is ideal to use if there Involves less overhead and can handle more
are only moderate amounts of event expected frequent events
It is cluster aware and runs only on the cluster Sling eventing is not cluster aware
2. Install the content package \Exercise_Files\12_Deep Dive into AEM APIs\ training-project-template.zip
with the completed project template.
3. Install the content package \Exercise_Files\12_Deep Dive into AEM APIs\ training-project-workflow.zip.
NOTE: If you want to learn more on how to create a project template, execute and build a workflow from
scratch, please refer to Appendix-Creating Projects&Worflows of this course.
1. Double-click the Eclipse shortcut on the desktop. The Eclipse Launcher opens.
2. Specify the Workspace as C:\Workspace and click Launch. The Eclipse Workspace opens.
5. In Eclipse, right-click com.adobe.training.core. and paste the file. The ApprovalStatusWriter.java class is
created, as shown:
1. package com.adobe.training.core;
2.
3. import com.adobe.granite.workflow.WorkflowSession;
4. import com.adobe.granite.workflow.WorkflowException;
5. import com.adobe.granite.workflow.exec.WorkItem;
6. import com.adobe.granite.workflow.exec.WorkflowProcess;
7. import com.adobe.granite.workflow.exec.WorkflowData;
8. import com.adobe.granite.workflow.metadata.MetaDataMap;
9.
10. import org.apache.sling.api.resource.ModifiableValueMap;
11. import org.apache.sling.api.resource.PersistenceException;
12. import org.apache.sling.api.resource.Resource;
13. import org.apache.sling.api.resource.ResourceResolver;
1. In Project Explorer, right-click training.core and choose Run As > Maven install. The build starts.
1. In the Workflow Models window, select Dynamic Editing, Approval, and Publish and click Edit, as
shown:
5. Select the Process tab and enter the following details, as shown:
• Name: Approval Status Writer
• Select the Handler Advance checkbox.
7. At this point the workflow is complete. In the top-right click Sync, as shown. This will write
the workflow model.
1. To test the new project, navigate to the AEM > Projects. Select Create > Project. The template opens.
2. Click Training Publishing Project, and click Next. The Create Project window opens.
• Enter Carlene Avery in the User field, ensure the dropdown beside it is set to Editors, and click Add.
4. Click Create in the top right corner. The Success pop-up window opens.
NOTE: At this point, you should be able to walk through the edit/approval steps. Even though the
tasks are assigned to different project groups, the admin can see and run through all the tasks.
10. Refresh the browser and notice the new Task, as shown:
13. Select Edit the Page, and click Complete, as shown. The Complete Task dialog box appears.
If you select Denied, the workflow will step back and create new task and re-edit the page with the
comments of the reviewer (cavery).
If you select Approved, the workflow will move forward.
19. Complete the task by selecting Approved and add a comment Approved. Click Complete.
Introduction
Organizations can use Adobe Experince Manager (AEM) to manage projects, workflows, assets, forms,
communities and integrations, and build websites and mobile apps. However, they need to ensure that
Objectives
A user refers to either a human user or an external system connected to the system. The user
account stores the user details needed for accessing AEM. Each user account is unique, and stores
the basic account details and privileges assigned.
Groups are collections of users and/or other groups. Their primary purpose is to simplify the
maintenance process by reducing the number of entities to be updated, as a change made to a
group is applied to all the members of the group.
• User Administration
• Group Administration
Access Right Management is important, especially with different users accessing and performing
different tasks within AEM. With the access control tab in CRXDE Lite, you can configure access
control policies and assign their corresponding privileges.
* (asterisk) Indicates that there is at least one local entry (either effective or
ineffective). These wildcard ACLs are defined in the content repository.
! (exclamation mark) Indicates that the permission is inherited, that is, there is at least one entry
that currently has no effect.
When you hover over the asterisk or exclamation mark, a tool tip provides more details about the
declared entries. The following table describes the two parts of the tool tip:
You can perform actions on a page (resource). For each page in the hierarchy, you can specify the action
the user can take on that page. Permissions enable you to allow or deny an action. The following table
describes the actions:
Action Description
Read The user can read the page and all the child pages.
Modify The user can modify the existing content on the page and on all the child pages. The
user can create new paragraphs on the page or any child page. At the JCR level, users
can modify a resource by modifying its properties, locking, visioning, and nt-
modifications, and they have complete write permission on nodes defining a jcr:content
child node, such as cq:Page, nt:file, and cq:Asset.
Create The user can create a new page or child page. If the Modify action is denied, the
subtrees below jcr:content are specifically excluded as the creation of jcr:content and its
child nodes are considered a page modification. This only applies to nodes defining a
jcr:content child node.
Delete The user can delete the existing paragraphs from the page or any child page. If the
Modify action is denied, any subtrees below jcr:content are specifically excluded as
removing jcr:content and its child nodes is considered a page modification. This only
applies to nodes defining a jcr:content child node.
Read ACL The user can read the ACL of the page or child pages.
Replicate The user can replicate content to another environment. For example, the user can
replicate content from an author instance to a pubic instance. This privilege is also
applied to any child pages.
Evaluating ACLs
AEM WCM uses ACLs to organize the permissions being applied to various pages. ACLs are made up of
individual permissions and are used to determine the order in which these permissions are applied. The
list is formed per the hierarchy of the pages under consideration. This list is then scanned bottom-up
When two concurrent (and opposing) permissions are listed on the same ACL for the same resource, the
permission at the bottom is applied to the resource.
If a user is part of the two groups allowed-it and restricted-it, you can see how access to the page
products is denied because the ACL deny in read access is the rule at the bottom.
If the order of the ACL is the opposite and a user is part of two groups, allowed-it and restricted-it, the
user will have access to the products page because the ACL allow in read access rule is at the bottom.
2. Click Adobe Experience Manager in the upper left of the screen, and then click the Tools icon, as
shown:
5. Enter your details such as your ID, email address, password, first name, and last name, as shown:
2. Click Adobe Experience Manager at the top left corner of the screen, and then click the Tools icon.
The success message is displayed on the Group Management page, as displayed below:
The group that you created will be added to the groups list, as shown:
2. Click Adobe Experience Manager in the upper left corner of the screen, and then click the Tools icon.
5. Select the Members tab. The Add Members to this Group appears.
7. Click Save & Close. The success message is displayed on the Group Management page
8. Look for the Contributors group from the list, and then click the Contributors. Edit Group Settings wizard
appears.
10. Click Adobe Experience Manager on the upper left corner of the screen, and then
click the Tools icon.
12. Double-click your ID (for example, cgrant) in the left pane to view various properties,
groups, and permissions associated with the user in the right pane.
The screenshot below shows the weretail folder under “apps” with “read” access selected:
1. Launch Eclipse by double-clicking the Eclipse shortcut on the desktop. The Eclipse Launcher opens.
2. Specify the Workspace as C:\Workspace and click Launch. The Workspace opens.
5. In Eclipse, right-click com.adobe.training.core and paste the file. The AutoAssignACL.java class is created,
as shown:
1. package com.adobe.training.core;
2.
3. import javax.jcr.security.AccessControlList;
4. import javax.jcr.security.AccessControlManager;
5. import javax.jcr.security.Privilege;
6. import javax.jcr.Session;
7.
8. import org.osgi.service.component.annotations.Component;
9.
10. import org.apache.jackrabbit.api.security.user.Authorizable;
11. import org.apache.jackrabbit.api.security.user.UserManager;
12. import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
13. import org.apache.sling.jcr.base.util.AccessControlUtil;
7. In Project Explorer, right-click training.core and choose Run As > Maven install. The build starts.
1. In a previous module (Deep_Dive_into_AEM_APIs) , you created a custom project and custom workflow.
If you do not have these exercises completed, install:
• training-project-template.zip
• training-project-workflow.zip
3. Drag and drop Process Step from the Workflow section to the area with the dotted line Drop steps or
participants here, as shown:
Process: Auto Assign Edit Permissions (created when you added the AutoAssignACL.java class)
Arguments: permission=add
8. Add another Process step from the Workflow section below the Approval Status Writer.
Arguments: permission=remove
12. Verify your completed workflow looks similar to the picture, as shown:
Because our Java class implements the Workflow Process service, the workflow-process-service service
user is the user that updates permissions for our editors. To allow the workflow-process-service to do
this, you need to give workflow-process-service the Read and Edit ACL permissions.
2. In the AEM Security console, serach for the user named workflow-process-service, as shown:
You now have your business process created that was outlined by your Project Manager. You have an
AEM Project template that uses our custom workflow that implements our auto assign ACL java class.
In this last step, you will run through the AEM Project as the Project Manager.
6. Choose Training Publishing Project and click Next. The Project opens.
11. In the Start Workflow screen, Select Dynamic Editing, Approval, and Publish and click Next.
The Properties screen opens.
15. Refresh the browser and notice the new task, as shown:
20. Notice the page is in the workflow and you have the option to edit the page:
23. Make changes to the Title and click Done. The changes are saved.
24. Verify the page has updated with the changed you made.
32. Click Complete and notice there is a dropdown with Approved and Denied.
If you select Denied, the workflow will step back and create new task for Chuck to re-edit the page
with the comments of the Reviewer (Carlene). Otherwise, if you select Approved, the workflow will
move forward.
and notice you have only the read permissions as the edit permissions have been
removed, as shown:
ACL automation:
https://jackrabbit.apache.org/oak/docs/security/accesscontrol/editing.html
https://docs.adobe.com/docs/en/spec/jsr170/javadocs/jcr-2.0/javax/jcr/security/AccessControlManager.html
http://aempodcast.com/2017/apache-sling/sling-resource-api-vs-jcr-api/
https://www.slideshare.net/connectwebex/jcr-sling-or-aem-which-api-should-i-use-and-when
https://stackoverflow.com/questions/3908584/when-to-use-jcr-content-repository-over-other-options
Introduction
In Adobe Experience Manager (AEM), the testing frameworks, such as Maven, Mockito, Sling JUnit, and
Hobbes tests help automate the testing process. Unit tests in AEM can be set up and run very quickly
outside any container. Integration tests can run within an AEM instance. The idea of writing tests in
AEM is to detect defects as early as possible, ultimately reducing cost. This testing module is based on
how the AEM Archetype approaches testing in a real project.
• Verification errors are clean—click on stack trace to see failed verification in test. Click on
exception's cause to navigate to actual interaction in code. Stack trace is always clean.
• Integration tests against a Sling instance that is started during the Maven build cycle or
independently
• Scriptable test nodes are executed only if they belong to the Sling’s ResourceResolver search path.
For example, /libs or /apps.
• Notify respective users of the status of the build, whether the build is a success or failure.
If you are working on an AEM project, here is how you can use Jenkins:
• Work on the feature or bug fix.
• Commit or push the changes to the central repository. For example, SVN or GIT.
• Have Jenkins configured to kick start the build production, and deploy packages to the AEM
Integration Server.
• QA team will pick up the feature or bug-fix, and test code changes on the Integration Server.
NOTE: If the build is not successful, Jenkins can identify the faulty source code that was
checked in to the repository, and then notify the developer of the error. This must be fixed
before the next build process can take place.AEM plug-in for Eclipse
1. Launch Eclipse by double-clicking the Eclipse shortcut on the desktop. The Eclipse Launcher
opens.
1. package com.adobe.training.core.models;
2.
3. import static org.junit.Assert.assertFalse;
4. import static org.junit.Assert.assertNotNull;
5. import static org.junit.Assert.assertTrue;
6. import static org.mockito.Mockito.mock;
7. import static org.mockito.Mockito.when;
8.
9. import java.text.SimpleDateFormat;
10. import java.util.Calendar;
11. import java.util.Date;
12. import java.util.Random;
13.
8. Right-click StockModelMockitoTest.java and select Run As > Junit Test. The Junit Test starts.
NOTE: Alternatively, you can run all the tests under src/test/java by right-clicking training.core and
selecting Run As > Maven test.
NOTE: This dependency allows you to use the Sling Mocks framework. Sling Mocks allow you to create
mock resources to test our different classes. Mock resources can be autogenerated using JSON files.
1. package com.adobe.training.core.models;
2.
3.
4. import static org.junit.Assert.assertEquals;
5. import static org.junit.Assert.assertNotNull;
6.
7. import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
8.
9. import org.apache.sling.testing.mock.sling.ResourceResolverType;
10. import org.apache.sling.testing.mock.sling.junit.SlingContext;
11.
12. import org.junit.Before;
13. import org.junit.Rule;
14. import org.junit.Test;
15.
16.
17. /**
18. * Tests the StockModelAdaptFromRequest using the Sling Mock implementation for Sling APIs
19. *
20. * A Sling context (the mock environment) needs to be created to test the classes.
25. *
26. * Note that the testable class is under /src/main/java:
27. * com.adobe.training.core.models.StockModelAdaptFromRequest.java
28. *
29. * To correctly use this testing class:
30. * -
put this file under training.core/src/test/java in the package com.adobe.training.core.models
31. *
5. Examine the code. Observe how the mock test loads a json file named /adbe-content.json.
7. Right-click src/test and select New > Source Folder. The New Source Folder screen opens.
1. Right-click StockModelSlingMockTest.java and select Run As > Junit Test. The test runs.
NOTE: This dependency allows you to use the Sling Mocks framework. Sling Mocks allow you to create
mock resources to test our different classes. Mock resources can be autogenerated using JSON files.
1. package com.adobe.training.core;
2.
3. import org.apache.commons.lang3.StringUtils;
4. import org.slf4j.Logger;
5. import org.slf4j.LoggerFactory;
6.
7. import com.day.cq.wcm.api.Page;
8.
9. public class PageHelper {
10.
11. private static final Logger LOGGER = LoggerFactory.getLogger(PageHelper.class);
12.
13.
14. /**
15. * Returns the page title of the given page. If the page title is empty it will fallback to the title and to the
16. * name of the page.
17. * @param page The page.
18. * @return The best suited title found (or <code>null</code> if page is <code>null</code>).
19. */
20. public static String getPageTitle(final Page page) {
21. if (page != null) {
22. final String title = page.getPageTitle();
23. if (StringUtils.isBlank(title)) {
24. return getTitle(page);
25. }
26. return title;
27. } else {
28. LOGGER.debug("Provided page argument is null");
29. return null;
30. }
31. }
32.
33. /**
NOTE: Now that you have your PageHelper class, you can test it. You will create a AEM Mock class
and the json with our test data.
6. In Eclipse, right-click src/test/java and select New > class. The New Java class window opens.
• Package: com.adobe.training.core
• Name: PageHelperAEMMockTest
10. In Eclipse, double-click PageHelperAEMMockTest.java in the editor, and replace the content
with the one copied from the exercise file.
1. package com.adobe.training.core;
2.
3. import static org.junit.Assert.assertEquals;
4.
5. import org.junit.Before;
6. import org.junit.Rule;
7. import org.junit.Test;
8.
9. import com.day.cq.wcm.api.Page;
10.
11. import io.wcm.testing.mock.aem.junit.AemContext;
12.
13. public class PageHelperAEMMockTest {
13. Examine the code. Observe how the mock test loads a json file named /trainingproject-
content.json.
1. Right-click PageHelperAEMMockTest.java and select Run As > Junit Test. The test runs.
Introduction
The AEM Projects feature helps manage and group all workflows and tasks associated with creating content in
AEM Sites and Assets.
• Execute a workflow
21
Exercise 1: Create a project template
When creating custom business processes in AEM, a custom project might be required. In this exercise, you will
create a project template, remove unnecessary tiles from the template, add a custom workflow, and add a new
group called reviewers.
In CRXDE Lite, navigate to /apps/trainingproject, right-click trainingproject, and click Create >
4. Right-click projects, and click Create > Create node. Enter the following values, as shown:
21
5. Click OK. The node is created.
7. Copy /libs/cq/core/content/projects/templates/default to
/apps/trainingproject/projects/templates.
21
9. Click Save All. Your changes are saved.
• gadgets/experiences
• gadgets/asset
• Workflows/models/launch
• Wokflow/models/landing
• Workflow/models/email
21
13. Click Save All. Your changes are saved.
21
14. Rename workflows/models/sampleworkflow to dynamicediting, as shown:
Note: This workflow named dynamicediting (the value you entered for the modelId in the
current step) does not exist yet, you will create it later.
16. Click Save All. Your changes are saved.
17. Right-click training-project node, and click Create > Create node. The Create Node dialog box
opens.
18. In the Create Node dialog box, enter the following values, as shown:
• Name: roles
21
19. Click OK. The roles node is created.
23. Navigate to the AEM > Projects. The Projects Console opens, as shown:
21
24. Select Create > Project. The template opens.
25. Select Training Publishing Project, and click Next. The Create Project window opens.
o Enter Carlene Avery in the User field, ensure the dropdown beside it is set to Editors, and click
Add.
o Enter Iris Mccoy in the User field, ensure the dropdown beside it is set to Reviewers, and click
Add.
21
27. Click Create in the top right corner. The Success pop-up window opens.
28. Click Open in the pop-up window. Observe the changes of the custom project, as shown:
21
Exercise 2: Execute a workflow
In this exercise, you will create a launcher that will trigger the workflow. You will manually start a workflow from
the workflow console and implement a process step in an existing workflow.
1. In AEM, navigate to Tools > Workflow > Models, as shown:
3. Click the checkmark on the Request for Activation workflow/card. The Request for Activation
workflow/card is selected. A blue highlight appears, as shown.
21
4. Click Start Workflow in the top left corner, as shown. The Run Workflow dialog box opens.
7. Click the Inbox at the top right corner. A notification will appear in the Inbox (top right) to
approve page content, as shown:
21
ADOBE COPYRIGHT PROTECTED
Note: The page will not be published until it is approved. Recall the process is of two steps:
21
Exercise 3: Build and test a workflow
In this exercise, you will create a workflow with two tasks - editing and approving. After the content is
approved, it will be published. If it is not approved, it will go back to the editor for a proper feedback loop.
Following are the two tasks in this exercise:
1. Build a workflow
In AEM, navigate to Tools > Workflow > Models, as shown. The Workflow Models window opens.
21
ADOBE COPYRIGHT PROTECTED
Click Done. The Dynamic Editing, Approval, and Publish model is created.
In the Workflow Models window, select the checkmark on the model Dynamic Editing, Approval, and
Publish and click Edit, as shown:
21
The Workflow Model Dynamic Editing, Approval, and Publish opens for editing, as shown:
Drag the Create Project Task component from the left-hand side into the Drag components here box.
Double-click Project Task Creation Step. The Project Task dialog box opens.
21
ADOBE COPYRIGHT PROTECTED
Click the Task tab and enter the following details:
Select the Advanced Settings tab, and copy and paste the contents from the Editor Script /Exerc-
se_Files/12_Deep_Dive_into_AEM_APIs/workflow-script.txt, as shown:
Click the Done icon (checkmark) on the top of the dialog box to save the changes.
21
Drag and drop another Create Project Task component from the left-hand side below Edit the Page in the
model, as shown:
21
Select the Routing tab, and add the following actions, as shown:
• Approved
• Denied
Click the Done icon (checkmark) on the top of the dialog box to save the changes.
Drag another OR Split component from the left-hand side below Approval in the model, as shown:
21
Double-click OR Split. The OR Split Properties dialog box opens.
Select the Branch1 tab, and copy and paste the contents of Or Split Branch 1 Scripts from /Exerc-
se_Files/12_Deep_Dive_into_AEM_APIs/workflow-script.txt.
Select the Branch2 tab, and copy and paste the contents of Or Split Branch 2 Script from /Exerc-
se_Files/12_Deep_Dive_into_AEM_APIs/workflow-script.txt, as shown.
21
ADOBE COPYRIGHT PROTECTED
Click the Done icon (checkmark) on the top of the dialog box to save the changes.
In the left branch (Branch 1), drag the Goto Step component and Open the dialog box.
Script: Copy and Paste the “GOTO Script” from the workflows-script.txt, as shown:
21
Click the Done icon (checkmark) on the top of the dialog box to save the changes.
21
In the right branch (Branch 2), drag the Activate Page/Asset component, as shown:
21
Task 2: Test the workflow
Recall the custom project you created earlier, you referenced the workflow you just created. To view this
connection, go to /apps/trainingproject/projects/templates/training-
project/workflows/models/dynamicediting. To test your workflow, you will open the newly created project
and test the workflow with it.
21
3. In the Workflow tile, click Add Work. The Start Workflow window opens, as shown:
4. Select Dynamic Editing, Approval, and Publish and click Next, as shown. The Properties window opens.
21
5. Enter the details, as shown:
• Title: Edit the Equipment Page
Note: At this point, you should be able to walk through the edit/approval steps. Even though
the tasks are assigned to different project groups, the admin can see and run through all the
tasks.
21
7. Refresh the browser and notice the new Task, as shown:
21
10. Select the Edit the Page and click Complete, as shown:
21
14. Impersonate as Carlene Avary, and click OK, as shown:
If you select Denied, the workflow will step back and create new task and re-edit the page with the comments
of the reviewer (cavery).
If you select Approved, the workflow will move forward.
21
16. Complete the task by selecting Approved and add a comment, as shown:
21