Core Components

In Adobe Experience Manager, components are the structural elements that constitute the content of the pages being authored. Components have always been a fundamental element of the AEM experience, making page creation simple but powerful for the author and the creation of new components flexible and extensible for the developer.

In AEM 6.3 Core Components were introduced to provide robust and extensible base components, built on the latest technology and best practices. Core components make page authoring more fleixble and customizable and the extending them is simple for the developer to offer custom functionality.

Versions and Releases

Core Components are distributed via GitHub. This will allow Adobe to more quickly add functionality to the components and also allow for community input.

In the past, the Foundation Components were tied to a specific version of AEM. Going forward, the Core Components will be made available with defined AEM versions with which they are compatible. Therefore one AEM version may support multiple versions or releases of the Core Components.

Versions

The major iteration of the Core Components are the versions. Versions are denoted with a nonzero, positive integer and introduce new components, features to existing components, and additional new functionality.

Developers and administrators can recognize versions of the core components via by a number in their resource type path, and in the fully qualified Java class names of their implementations. This version number represents a major version as defined by semantic versioning guidelines, which is incremented only for changes that are not backward-compatible.

For more details about core component versions, see the developer documentation of the Core Components.

Releases

The minor iteration of the Core Components are the releases. Releases are denoted with two nonzero, positive decimals appended to the version number. Releases represent the actual published artifacts available on GitHub and contain mostly bug fixes and improvements with occasional new features.

A version can have multiple releases.

Compatability

The following table provides an overview of the currently available and supported AEM versions and Core Components releases and their mutual compatibility.

AEM Version Core Components v1

Release 1.0.0 – 1.0.6

Core Components v1

Release 1.1.0

AEM 6.1 Not Compatible Not Compatible
AEM 6.2 Not Compatible Not Compatible
AEM 6.3 Compatible Compatible*

Note:

* Using release 1.1.0 with AEM 6.3 requires feature packs to enable certain content services functionality

See the content services feature pack documentation for details.

Note:

Adobe recommends that developers use the latest release of the Core Components available to benefit from the most up-to-date fixes and features.

Note:

Core components are not immediately available to authors, the development team must first integrate them to your environment. Once integrated, they may be made available and pre-configured via the template editor or in design mode.

When to Use Core Components

As the Core Components are all-new for 6.3, and offer multiple benefits, it is recommended for new AEM projects to use them. For existing projects, a migration should be part of a larger project effort, for example a rebranding or overall refactoring.

Therefore, Adobe provides following recommendations:

  • New Projects
    Use the Core Components wherever they match the needs of the project, or optionally extend them.
    Except for the various Layout Containers and Paragraph Systems, don’t use the foundation components.
  • Existing Projects
    Recommendation is keep using the foundation components, unless a site or component refactoring is planned.
    As they are very widely used by most existing projects, the foundation components will continue to be supported.
  • New Custom Components
    Assess if an existing Core Component may be customized.
    If not, recommendation is to build a new custom component following the Component Guidelines.
  • Existing Custom Components
    If your components work as expected, then keep them as they are.
    If not, refer to “New Custom Components” above.

Core Components Support

Core Components are an integral part of AEM and supported as is, under the same terms and conditions as if they were delivered as part of the Quickstart.

Like other product features, the general rule of end-of-life is:

  • Components are first announced to be deprecated before being removed
  • At the earliest they are then removed from the AEM release following the announcement.

This gives customers at least one release cycle to move to the new version of the component, before support ends.

The version of each component clearly states the AEM versions that it supports. When support ceases for a version of AEM, then so does the support of the Core Components for that version of AEM.

For details about the support of component customizations, see the Customizing Core Components page of the relevant Core Components Version.

Foundation Component Support

Since the Foundation Components have served as a basis of so much project development over many versions, they will continue to be supported into the foreseeable future.

However, Adobe’s development emphasis has shifted to the Core Components and new features will be added to them whereas only bug fixes will be made to the Foundation Components

Version 1 was the first version of the Core Components with an initial compatibility with AEM 6.3. Version 1 introduced the basic components essential to page composition including:

Release 1.1.0 of the Core Components also introduced a new component to display content fragments as well as enabled JSON export for the existing components.

The We.Retail reference site illustrates how the core components can be used.

Authoring with Core Components

In Adobe Experience Manager, components are the structural elements that constitute the content of the pages being authored. This section covers the core components, which provide essential content types to create pages.

The core components have been introduced with AEM 6.3 and offer flexible and feature-rich authoring functionality. The We.Retail reference site illustrates how the core components can be used.

Note:

Core components are not immediately available to authors, the development team must first integrate them to your environment. Once integrated, they may be made available and pre-configured via the template editor or in design mode.

Caution:

Core components require AEM 6.3 and do not work with the Classic UI.

Authoring with the core components does not differ substantially from the foundation components.

However, as an author, you will notice several advantages of the core components, including:

The components are available on the Components tab of the side panel of the page editor when editing a page.

Components are grouped according to categories called component groups to easily organize and filter the components. The component group name is displayed with the component in the component browser and it is also possible to filter by group to easily find the right component.

Pre-Configuring Core Components

Configuring foundation components was the job of a developer. However with core components, a template author can now configure a number of capabilities via the template editor or in design mode.

For example if an image component should not allow image upload from the file system, or if a text component should only allow certain paragraph formatting, these features can be enabled or disabled with a simple click.

See Creating Page Templates for more information.

Edit and Design Dialogs

Because the core components can be pre-configured by template authors to define what options are allowed as part of a template, and then further configured by the page author to define actual page conent, each component can have options in two different dialogs.

Description What it Controls Examples
Edit Dialog Options that a page author can modify during normal page editing for the placed components The content displayed by the component and how it will ultimately appear on the page. Text formatting, image rotation
Design Dialog Options that a template author can modify when configuring a page template. What options the page author has available when editing the component Which text formatting options are available, which image in-place options are available

List of Core Components Available

The following is a list of the available core components linked to pages describing their edit and design dialog capabilities in detail.

Release 1.1.0 of the Core Components also introduced a new component to display content fragments as well as enabled JSON export for the existing components.

Note:

Depending on your instance you may have customized components developed explicitly for your requirements. These may even have the same name as some of the components discussed here.

Note:

The form core components are not related to AEM Forms.

Page Component

The Page Component is an extensible page component designed to work with the template editor and allow page header/footer and structure components to be assembled with the template editor.

Usage

The page component forms the basis of all pages designed with the core components as well as editable templates. By using the page component, headers, footers, and the structure of the page can be defined as a template using the other core components.

Using the design dialog, custom client-side libraries can be defined for the page. Unlike other components which have an edit dialog accessible directly from the component, because the component is the page itself, the edit dialog of the page component is the page properties window.

Title Component

The Core Component Title Component is a section heading component that features in-place editing.

Usage

The title component is intended to be used as the title or heading of a section of content. The available heading levels can be defined by the template author in the design dialog. The content editor can select from available headings levels in the edit dialog. For added convenience, simple in-place editing of the heading text is also available.

Text Component

The Text Component is a rich text editing and composing component that features in-place editing.

Usage

The text component offers a robust rich text editor that allows for easy text editing in a simplified, in-line editor as well as a full screen format.

The edit dialog features in-line editing with limited options with full functionality available in the full-screen edit dialog. Using the design dialog, text formatting options such as headings, special characters, and paragraph styles can be configured for the template for the content author.

Image Component

The Core Component Image Component is an adaptive image component features in-place editing.

Usage

The image component allows easy placement of image assets and offers in-place editing. It features adaptive image selection with lazy loading as well as cropping for the content author. The allowed image widths as well as cropping and additional settings can be defined by the template author in the design dialog. The content editor can upload or select assets in the configure dialog and crop the image in the edit dialog. For added convenience, simple in-place modification of the image is also available.

List Component

The Core Component List Component allows for the easy creation of dynamic as well as static lists.

Usage

The list component can be used to create for example a dynamic list of child pages or a static list of arbitrarily defined items. The type of lists available and formatting options can be defined by the template author in the design dialog. The content editor can select from available list types and how to format the list elements in the edit dialog.

Breadcrumb Component

The Core Component Breadcrumb Component is a navigation component that builds a breadcrumb of links based on the page’s location in the content hierarchy.

Usage

The breadcrumb component displays the position of the current page within the site hierarchy, allowing page visitors to navigate the page hierarchy from their current location. This is often integrated into page headers or footers. Available options such as the default navigation level and the ability to show the current page or hidden pages can defined by the template author in the design dialog. The content editor can then choose if hidden pages should be shown or not and the actual navigation level for hte component in the edit dialog.

Sharing Component

The Core Component Sharing Component is a Facebook and Pinterest sharing widget.

Usage

The sharing component adds Facebook and Pinterest sharing links to the page. It is often included in page headers or footers. Unlike other components, the settings for the sharing component is done by the template author via Intial Page properties and by the content author via Page Properties.

Form Container Component

The Core Component Form Container Component allows for the creation of simple submission forms.

Usage

The form container component enabled the building of simple information submission forms and features by supporting simple WCM forms and by using a nested structure to allow additional form components. By using the setting dialog the content editor can define what type of action form submission triggers, where the submitted content should be stored, and if a workflow should be triggered. The template author can use the design dialog to define the allow components and their mappings similar to the design dialog for the standard layout container in the template editor.

Form Text Component

The Core Component Form Text component allows the entry of form text for submission.

Usage

The form text component allows for the submission of different types of text and is intended to be used along with the form container component. The type of text validation, labels, and help messages can be defined by the content editor in the configure dialog.

Form Options Component

The Core Component Form options component allows for the selection from pre-defined options in various formats.

Usage

The core component form options component allows for the submission of different types of options presented in many different ways and is intended to be used along with the form container component. The presentation of the options, labels, and individual options can be defined by the content editor in the configure dialog.

Form Hidden Component

The Core Component Form Hidden component allows for the display of a hidden field.

Usage

The core component form hidden component allows for the creation of hidden fields to pass information about the current page back to AEM and is intended to be used along with the form container component. The field properties can be defined by the content editor in the configure dialog.

Form Button Component

The Core Component Form Hidden component allows for the inclusion of a hidden field in a form.

Usage

The core component form button component allows for the creation of button field, often to trigger the submission of the field and is intended to be used along with the form container component. The button properties can be defined by the content editor in the configure dialog.

Developing Core Components

The core components have been released for AEM version 6.3. They provide robust and extensible base components, and their highlights are:

 

Caution:

Core Components require AEM 6.3 and Java 8.

Core Components do not work with the Classic UI.

Delivered over GitHub

The Core Components are developed in and delivered through GitHub.

CODE ON GITHUB

You can find the code of this page on GitHub

See the Using Core Components documentation page to learn how to get started using them in your project.

Having the Core Components on GitHub will allow to do frequent updates, and to listen to the feedback from the AEM developer community. Also, this should help customers and partners to follow similar patterns when building custom components.

Sample Content Run-Mode

The Core Components are visible in the Quickstart when the sample content is present, because the We.Retail reference site uses them. However, when running in production (in nosamplecontent runmode, without sample content enabled), the core components won’t be present anymore and must be installed on the AEM instances by the development and/or operations team.

Note:

In production environments, always run the Quickstart in nosamplecontent runmode. To use the Core Components in nosamplecontent runmode, follow the instructions of the Using Core Components documentation page.

Technical Capabilities

The following table gives an overview of the differences between core components and foundation components.

For details about their authoring capabilities and options to pre-configurable them, refer to the authoring page about them.

Capability Core Component Foundation Component
Logic implementation Java POJOs with Sling Models annotations JSP code
Markup definition HTML Template Language (HTL) syntax JSP code
XSS sanitization Automated by HTL Mostly manual
CSS classes naming Standardized naming convention inspired by Bootstrap Custom schemes
Dialog definition Coral 3 Coral 2 + Classic UI
JSON output Sling Models Exporter with Jackson serialization Default Sling servlet
Versioning For the model and the HTL None
Testing Unit Tests + Integration Tests Integration Tests
Delivery Via public GitHub Via Quickstart
License Apache License Adobe proprietary
Contribution Via pull request Not possible

Component List

The following table lists the available Core Components, linking to their API, and indicates which foundation components they replace.

Core Component Description Replaced Foundation Components
Page Responsive page working with template editor /libs/foundation/components/page
/libs/wcm/foundation/components/page
Breadcrumb Page hierarchy navigation /libs/foundation/components/breadcrumb
Title H1-H6 title /libs/foundation/components/title
/libs/wcm/foundation/components/title
Text Rich text /libs/foundation/components/text
/libs/foundation/components/table
/libs/wcm/foundation/components/text
Image Smart and lazy loading of optimal rendition size /libs/foundation/components/image
/libs/foundation/components/adaptiveimage
/libs/foundation/components/logo
/libs/foundation/components/mobileimage
/libs/foundation/components/mobilelogo
/libs/wcm/foundation/components/image
List List of pages /libs/foundation/components/list
/libs/foundation/components/mobilelist
/libs/wcm/foundation/components/list
Sharing Facebook and Pinterest sharing widget
Form Container Responsive form paragraph system /libs/foundation/components/form/start
/libs/foundation/components/form/end
Form Text Text input field /libs/foundation/components/form/text
/libs/foundation/components/form/password
Form Options Multiple options input field /libs/foundation/components/form/checkbox
/libs/foundation/components/form/radio
/libs/foundation/components/form/dropdown
Form Hidden Hidden input field /libs/foundation/components/form/hidden
Form Button Submit or custom button /libs/foundation/components/form/submit

Upcoming components

Following core components are being actively worked on. They haven’t been released yet, but can be previewed in the development branch:

  • Navigation – a site navigation component that lists the nested page hierarchy
  • Language Navigation – a language and country switcher that lists the global language structure
  • Quick Search – a search component that displays the results as real-time suggestions in a drop-down menu
  • Teaser – a component to link to a different page with a preview image, title and description

Also, a styling capability is in the works, which will be released as a feature pack for 6.3, and will be implemented by all the core components. This will allow to define on the template different styles for each component, which the authors can then apply to the component instances. A very first tech preview of that feature is available through cq-6.3.0-featurepack-18678.

Upgrade of Core Components

One benefit of versioned components is that it allows to separate the migration to a new AEM version from the migration to new component versions. Also, if new component versions are available, it allows for the individual migration of each component to the new version.

Migrations to a new AEM version won’t impact how the Core Components work, provided that their versions also support the new AEM version that is being migrated to. Customizations made to the Core Components should not be affected either, as long as they don’t use APIs that have been deprecated or removed.

Migrations to new versions of the Core Components won’t impact how the component works either, but new features might be introduced to page authors, which might require some configuration by a template editor, in case the default behavior isn’t desired. Customizations however might need to be adapted, for more details see the Customizing Core Components page.

When to Use the Core Components?

As the Core Components are all-new for 6.3, and offer multiple benefits, it is recommended for new AEM projects to use them. For existing projects, a migration should be part of a larger project effort, for example a rebranding or overall refactoring.

Therefore, Adobe provides following recommendations:

  • New Projects
    Use the Core Components wherever they match the needs of the project, or optionally extend them.
    Except for the various Layout Containers and Paragraph Systems, don’t use the foundation components.
  • Existing Projects
    Recommendation is keep using the foundation components, unless a site or component refactoring is planned.
    As they are very widely used by most existing projects, the foundation components will continue to be supported.
  • New Custom Components
    Assess if an existing Core Component may be customized.
    If not, recommendation is to build a new custom component following the Component Guidelines.
  • Existing Custom Components
    If your components work as expected, then keep them as they are.
    If not, refer to “New Custom Components” above.

Core Component Support

Core Components are an integral part of AEM and supported as is, under the same terms and conditions as if they were delivered as part of the Quickstart.

Like other product features, the general rule is: Components are 1st announced to be deprecated, and the earliest removed for the following AEM release. That gives customers at least one release cycle to move to the new version of the component, before dropping its support.

The version of each component clearly states the AEM versions that it supports. When support ceases for a version of AEM, then so does the support of the Core Components for that version of AEM.

For details about the support of component customizations, see the Customizing Core Components page.

Foundation Component Support

Since the foundation components have served as a basis of so much project development over many versions, they will continue to be supported into the foreseeable future.

However, Adobe’s development emphasis has shifted to the core components and new features will be added to them whereas only bug fixes will be made to the foundation components

Component Guidelines

The Core Components follow modern implementation patterns that are quite different from the foundation components.

This page explains these patterns, and when to use them to build your own authorable components. The first section “General Component Patterns” applies to any kind of component, while the second section “Reusable Component Patterns” applies to components that are intended to be reused across sites or projects, like the Core Components for instance.

General Component Patterns

The guidelines in this section are recommended for any kind of component, regardless whether the component is specific to a single project, or whether the component is meant to be widely reused across sites or projects.

Configurable Components

Components can have dialogs with a variety of options. This should be leveraged to make components flexible and configurable, and avoid implementing multiple components that are mostly variations of each other.

Typically, if a wireframe or design contains variations of similar elements, these variations should not be implemented as different components, but as the one component with options to choose between the variations.

To take this a step further, if components are reused across sites or projects, also look the Pre-Configurable Capabilities section.

Separation of Concerns

Keeping the logic (or model) of a component separate from the markup template (or view) is usually a good practice. There are several ways to achieve that, however the recommended one is to use Sling Models for the logic and the HTML Template Language (HTL) for the markup, like the Core Components also do.

Sling Models are a set of Java annotations to easily access needed variables from POJOs, and therefore offer a simple, powerful and performant way to implement Java logic for components.

HTL has been designed to be a secure and simple template language that is tailored for AEM. It can call many forms of logic, which makes it very flexible.

Reusable Component Patterns

The guidelines in this section can be used as well for any kind of component, but they make most sense for components that are intended to be reused across sites or projects, like the Core Components for instance. These guidelines can therefore be ignored for components that are only used on a single site or project.

Pre-Configurable Capabilities

In addition to the edit dialog that is used by page authors, components can also have a design dialog for template authors to pre-configure them. The Template Editor allows to setup all these pre-configurations, which are called “Policies”.

To make components as reusable as possible, they should be provided with meaningful options to pre-configure. This will allow to enable or to disable features of the components to match the specific needs of different sites.

Proxy Component Pattern

As each content resource has a sling:resourceType property that references the component to render it, it is usually good practice to have these properties pointing to site-specific components, instead of pointing to components that are shared by multiple sites. This will offer more flexibility and avoid content refactoring if one site needs a different behavior for a component, because this customization can then be achieved on the site-specific component and won’t affect the other sites.

However, for the project-specific components no not duplicate any code, they should each refer to the shared parent component with the sling:resourceSuperType property. These project-specific components that mostly just refer to parent components are called “proxy components”. Proxy components can be entirely empty if they fully inherit the functionality, or they can redefine some aspects of the component.

Component Versioning

Components should be kept fully compatible over time, yet sometimes changes that cannot be kept compatible are necessary. One solution to these opposing needs is to introduce component versionning by adding a number in their resource type path, and in the fully qualified Java class names of their implementations. This version number represents a major version as defined by semantic versioning guidelines, which is incremented only for changes that are not backward-compatible.

Component versioning creates a form of contract that is important for upgrades as it clarifies when something might need to be refactored. See also the section Upgrade Compatibility of Customizations, which details what form of customization detailed version policy for the Core Components.

To avoid painful content migrations, it is important to never directly point to versioned components from content resources. As rule of thumb, a sling:resourceType of the content must never have a version number in it, or upgrading components will require the content to be refactored too. The best way to avoid this is to follow the Proxy Component Pattern described above.

Model Interfaces

This pattern is about HTL’s data-sly-use instruction to point to a Java interface, while the Sling Model implementation is also registering itself to the resource type of the component.

When combined with the Proxy Component Pattern described above, this form of double-binding offers following nice extension points:

  1. A site can redefine the implementation of a Sling Model by registering it to the resource type of the proxy component, without having to mind about the HTL file, which can still point to the interface.
  2. A site can redefine the HTL markup of a component, without having to mind about which implementation logic it should point to.

Putting it all together

Below is an overview of the entire resource type binding structure, taking the example of the Title Core Component. It illustrates how a site-specific proxy component allows to resolve component versioning, to avoid that the content resource contains any version number. It then shows how the component’s title.html HTL file uses to the model interface, while the implementation binds to the specific version of the component through Sling Model annotations.

chlimage_1

Below is another overview, which doesn’t show the details of the implementation POJO, but reveals how the associated templates and policies are referenced.

The cq:allowedTemplates property tells which templates can be used for a site, and the cq:template tells for each page what the associated template is. Every template is made of following three parts:

  • structure contains the resources that will be forced on each page to be present, and that the page author won’t be able delete, like for instance the page header and footer components.
  • initial contains the initial content that will be duplicated to the page when it is created.
  • policies contains for each component the mapping to a policy, which is the component’s pre-configuration. This mapping allows policies to be reused across templates, and therefore to be centrally managed.
chlimage_1

Advertisement

Touch UI and Classic UI

The touch-enabled UI is now the standard UI for AEM, though the classic UI is still supported.

 

The touch-enabled UI has been designed by Adobe to provide consistency in the user experience across multiple products. It is based on:

  • Coral UI (CUI) an implementation of Adobe’s visual style for the touch-enabled UI. Coral UI provides everything your product / project / web application needs to adopt the UI visual style.
  • Granite UI components are built with Coral UI.

Differences with the Classic UI

The differences between Granite UI and ExtJS (used for the classic UI) are also of interest:

ExtJS Granite UI
Remote Procedure Call State Transistions
Data transfer objects Hypermedia
Client knows server internals Client does not know internals
“Fat client” “Thin client”
Specialized client libraries Universal client libraries

Coral UI

Coral UI (CUI) is an implementation of Adobe’s visual style for the touch-enabled UI, that has been designed to provide consistency in the user experience across multiple products. Coral UI provides everything you need to adopt the visual style used on the authoring environment.

Caution:

Coral UI is a UI library made available to AEM customers for building applications and web interfaces within the boundaries of their licensed use of the product.

Use of Coral UI is only permitted:

  • When it has been shipped and bundled with AEM.
  • For use when extending the existing UI of the authoring environment.
  • Adobe corporate collateral, ads, and presentations.
  • The UI of Adobe-branded applications (the font must not be readily available for other uses).
  • With minor customizations.

Use of Coral UI should be avoided in:

  • Documents and other items not related to Adobe.
  • Content-creation environments (where the preceding items might be generated by others).
  • Applications/components/web pages that are not clearly connected to Adobe

TOUCH-OPTIMIZED UI(Graphite UI)

This UI was meant to address the growing need for authors to be able to create and edit content on their tablets and phones while on the go. Touch UI is designed with the author in mind, allowing for easy updates using a touch-device, while still supporting navigation with a mouse for users working on a laptop or desktop.

This is based on CORAL UI(Adobe product). CORAL UI will provide common look and feel for all Adobe marketing cloud solutions.

If we used editor.html then touch ui will be opened

When editing pages in AEM, several modes are available; including, in the touch-optimized UI, Developer mode. This opens a side panel with several tabs that provide a developer with infomation about the current page. The three tabs are:

Components for viewing sructure and performance information.

Tests for running tests and analyzing the results.

Errors to see any problems occuring.

CLASSIC UI

Classic UI is used for desktop applications. This is not responsive

Its Based on EXT JS framework(Sencha).Widgets,dialogs are based on EXT.js

if we used cf# then classic mode will be opened

Dialog creation is separate for Classic and touch

HTL AEM6.3

Formerly Known As “Sightly”

HTML Template Language (also referred to as HTL) is Adobe Experience Manager’s preferred and recommended server-side template system for HTML.  As in all HTML server-side templating systems, a HTL file defines the output sent to the browser by specifying the HTML itself, some basic presentation logic and variables to be evaluated at runtime.

Advantages

  • HTL is capable of automatically applying the proper context-aware escaping to all variables being output to the presentation layer(expressions placed in href or src attributes to be escaped differently from expressions placed in other attributes).
  • always enforcing strict separation of concerns between markup and logic.
  • allow HTML developers without Java knowledge and with little product-specific knowledge to be able to edit HTL templates, allowing them to be part of the development team

 

HTL over JSP

It is recommended for new AEM projects to use the HTML Template Language, as it offers multiple benefits compared to JSP. For existing projects though, a migration only makes sense if it is estimated to be less effort than maintaining the existing JSPs for the coming years.

Even within the same component, HTL files can be used alongside JSPs and ESPs. Following example shows on line 1 how to include an HTL file from a JSP file, and on line 2 how a JSP file can be included from an HTL file:

<cq:include script="template.html"/>
<sly data-sly-include="template.jsp"/>

Fundamental Concepts of HTL

The HTML Template Language uses an expression language to insert pieces of content into the rendered markup, and HTML5 data attributes to define statements over blocks of markup (like conditions or iterations). As HTL gets compiled into Java Servlets, the expressions and the HTL data attributes are both evaluated entirely server-side, and nothing remains visible in the resulting HTML.

Blocks and Expressions

Here’s a first example, which could be contained as is in a template.html file:

<h1 data-sly-test="${properties.jcr:title}">
    ${properties.jcr:title}
</h1>
Two different kind of syntaxes can be distinguished:
  • Block Statements
    To conditionally display the <h1> element, a data-sly-test HTML5 data attribute is used. HTL provides multiple such attributes, which allow to attach behavior to any HTML element, and all are prefixed with data-sly.
  • Expression Language
    HTL expressions are delimited by characters ${ and }. At runtime, these expressions are evaluated and their value is injected into the outgoing HTML stream.

The SLY Element

Note:

The SLY element has been introduced with AEM 6.1, or HTL 1.1.

Prior to that, the data-sly-unwrap attribute had to be used instead.

 

Sometimes there might not be an existing element at the exact location where a block statement has to be inserted. For such cases, it is possible to insert a special SLY element that will be automatically removed from the output, while executing the attached block statements and displaying its content accordingly.

So following example:

<sly data-sly-test="${properties.jcr:title && properties.jcr:description}">
    <h1>${properties.jcr:title}</h1>
    <p>${properties.jcr:description}</p>
</sly>
will output something like following HTML, but only if there are both, a jcr:title and a jcr:decription property defined, and if none of them are empty:
<h1>MY TITLE</h1>
<p>MY DESCRIPTION</p>

One thing to take care though is to only use the SLY element when no existing element could have been annotated with the block statement, because SLY elements deter the value offered by the language to not alter the static HTML when making it dynamic.

For example, if the previous example would have been wrapped already inside a DIV element, then the added SLY element would be abusive:

<div>
    <sly data-sly-test="${properties.jcr:title && properties.jcr:description}">
        <h1>${properties.jcr:title}</h1>
        <p>${properties.jcr:description}</p>
    </sly>
</div>

 

and the DIV element could have been annotated with the condition:

<div data-sly-test="${properties.jcr:title && properties.jcr:description}">
    <h1>${properties.jcr:title}</h1>
    <p>${properties.jcr:description}</p>
</div>

 

HTL Comments

Following example shows on line 1 an HTL comment, and on line 2 an HTML comment:

<!--/* An HTL Comment */-->
<!-- An HTML Comment -->

 

 

HTML comments cannot contain HTL comments and vice versa.

Special Contexts

Element and Attribute Names

Expressions can only be placed into HTML text or attribute values, but not within element names or attribute names, or it wouldn’t be valid HTML anymore. In order to set element names dynamically, the data-sly-element statement can be used on the desired elements, and to dynamically set attribute names, even setting multiple attributes at once, the data-sly-attribute statement can be used.

<h1 data-sly-element="${myElementName}" data-sly-attribute="${myAttributeMap}">...</h1>

 

Contexts Without Block Statements

As HTL uses data attributes to define block statements, it is not possible to define such block statements inside of following contexts, and only expressions can be used there:

  • HTML comments
  • Script elements
  • Style elements

The reason for it is that the content of these contexts is text and not HTML, and contained HTML elements would be considered as simple character data. So without real HTML elements, there also cannot be data-sly attributes executed.

Following example illustrates the behavior for HTML comments, but in script or style elements, the same behavior would be observed:

<!--
    The title is: ${properties.jcr:title}
    <h1 data-sly-test="${properties.jcr:title}">${properties.jcr:title}</h1>
-->

will output something like following HTML:

<!--
    The title is: MY TITLE
    <h1 data-sly-test="MY TITLE">MY TITLE</h1>
-->

 

Explicit Contexts Required

One objective of HTL is to reduce the risks of introducing cross-site scripting (XSS) vulnerabilities by automatically applying context-aware escaping to all expressions. While HTL can automatically detect the context of expressions placed inside of HTML markup, it doesn’t analyze the syntax of inline JavaScript or CSS, and therefore relies on the developer to specify explicitly what exact context has to be applied to such expressions.

Since not applying the correct escaping results in XSS vulnerabilities, HTL does therefore remove the output of all expressions that are in script and style contexts when the context has not been declared.

Here is an example of how to set the context for expressions placed inside scripts and styles:

<script> var trackingID = "${myTrackingID @ context='scriptString'}"; </script>
<style> a { font-family: "${myFont @ context='styleString'}"; } </style>

General Capabilities of HTL

This section quickly walks through the general features of the HTML Template Language.

Use-API for Accessing Logic

Consider following example:

<p data-sly-use.logic="logic.js">${logic.title}</p>

 

And following logic.js server-side executed JavaScript file placed next to it:

use(function () {
    return {
        title: currentPage.getTitle().substring(0, 10) + "..."
    };
});

 

Automatic Context-Aware Escaping

Consider following example:

<p data-sly-use.logic="logic.js">
    <a href="${logic.link}" title="${logic.title}">
        ${logic.text}
    </a>
</p>

 

Assuming following logic.js file:

use(function () {
    return {
        link:  "#my link's safe",
        title: "my title's safe",
        text:  "my text's safe"
    };
});

 

The initial example will then result in following output:

<p>
    <a href="#my%20link%27s%20safe" title="my title's safe">
        my text's safe
    </a>
</p>

 

Automatic Removal of Empty Attributes

Consider following example:

<p class="${properties.class}">some text</p>

If the value of the class property happens to be empty, the HTML Template Language will automatically remove the entire class attribute from the output.

Additionally, the type of the variable placed in the expression matters:

  • String:
    • not empty: Sets the string as attribute value.
    • empty: Removes the attribute altogether.
  • Number: Sets the value as attribute value.
  • Boolean:
    • true: Displays the attribute without value (as a Boolean HTML attribute).
    • false: Removes the attribute altogether.

Here’s an example of how a Boolean expression would allow to control a Boolean HTML attribute:

<input type="checkbox" checked="${properties.isChecked}"/>

 

Common Patterns with HTL

 

Loading Client Libraries

In HTL, client libraries are loaded through a helper template provided by AEM, which can be accessed through data-sly-use. Three templates are available in this file, which can be called through data-sly-call:

  • css – Loads only the CSS files of the referenced client libraries.
  • js  – Loads only the JavaScript files of the referenced client libraries.
  • all – Loads all the files of the referenced client libraries (both CSS and JavaScript).

Each helper template expects a categories option for referencing the desired client libraries. That option can be either an array of string values, or a string containing a comma separated values list.

Here are two few short examples:

Loading multiple client libraries fully at once

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"
     data-sly-call="${clientlib.all @ categories=['myCategory1', 'myCategory2']}"/>

 

Referencing a client library in different sections of a page

<!doctype html>
<html data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
    <head>
        <!-- HTML meta-data -->
        <sly data-sly-call="${clientlib.css @ categories='myCategory'}"/>
    </head>
    <body>
        <!-- page content -->
        <sly data-sly-call="${clientlib.js @ categories='myCategory'}"/>
    </body>
</html>

 

In the second example above, in case the HTML head and body elements are placed into different files, the clientlib.htmltemplate would then have to be loaded in each file that needs it.

Passing Data to the Client

The best and most elegant way to pass data to the client in general, but even more with HTL, is to use data attributes.

Following example shows how the logic (which could also be written in Java) can be used to very conveniently serialize to JSON the object that is to be passed to the client, which can then very easily be placed into a data attribute:

<!--/* template.html file: */-->
<divdata-sly-use.logic="logic.js"data-json="${logic.json}">...</div>
/* logic.js file: */
use(function () {
    var myData = {
        str: "foo",
        arr: [1, 2, 3]
    };
    return {
        json: JSON.stringify(myData)
    };
});

 

From there, it is easy to imagine how a client-side JavaScript can access that attribute and parse again the JSON. This would for instance be the corresponding JavaScript to place into a client library:

var elements = document.querySelectorAll("[data-json]");
for (var i = 0; i < elements.length; i++) {
    var obj = JSON.parse(elements[i].dataset.json);
    //console.log(obj);
}

HTL Expression Language

The HTML Template Language uses an expression language to access the data structures that provide the dynamic elements of the HTML output. These expressions are delimited by characters ${ and }. To avoid malformed HTML, expressions can only be used in attribute values, in element content, or in comments.

<!-- ${component.path} -->
<h1 class="${component.name}">
    ${properties.jcr:title}
</h1>

Expressions can be escaped by prepended by a \ character, for instance \${test} will render ${test}.

The expression syntax includes variablesliteralsoperators and options:

Variables

Without having to specify anything, HTL provides access to all objects that were commonly available in JSP after including global.jsp. The Global Objects page provides the list of all objects provided access to by HTL.

Property Access

There are two ways to access properties of variables, with a dot notation, or with a bracket notation:

${currentPage.title}
${currentPage[‘title’]} or ${currentPage[“title”]}

The simpler dot notation should be preferred for most cases, and the brackets notation should be used to access properties that contain invalid identifier characters, or to access properties dynamically.

The accessed properties can be functions, however passing arguments is not supported, so only functions that don’t expect arguments can accessed, like getters. This is a desired limitation, which is intended to reduce the amount of logic embedded into expressions. If needed, the data-sly-use statement can be used to pass parameters to the logic.

Also shown in the example above is that Java getter functions, like getTitle(), can be accessed without prepending the get, and by lowering the case of the character that follows.

Valid Indentifier Characters

The names of variables, called identifiers, conform to certain rules. They must start with a letter (AZ and az), or an underscore (_), and subsequent characters can also be digits (09) or colon (:). Unicode letters such as å and ü cannot be used in identifiers.

Given that the colon (:) character is common in AEM property names, it is convenient that it is a valid identifier character:

${properties.jcr:title}

The bracket notation can be used to access properties that contain invalid identifier characters, like the space character in the example below:

${properties[‘my property’]}

Accessing Members Dynamically

1
${properties[myVar]}

Permissive Handling of Null Values

1
${currentPage.lastModified.time.toString}

 

Options

Expression options can act on the expression and modify it, or serve as parameters when used in conjunction with block statements.

Everything after the @ is an option:

1
${myVar @ optOne}

Options can have a value, which may be a variable or a literal:

1
2
3
4
${myVar @ optOne=someVar}
${myVar @ optOne='bar'}
${myVar @ optOne=10}
${myVar @ optOne=true}

Multiple options are separated by commas:

1
${myVar @ optOne, optTwo=bar}

Parametric expressions containing only options are also possible:

1
${@ optOne, optTwo=bar}

String Formatting

Option that replaces the enumerated placeholders, {n}, with the corresponding variable:

1
${'Page {0} of {1}' @ format=[current, total]}

Internationalization

Translates the string to the language of the current source (see below), using the current dictionary. If no translation is found, the original string is used.

1
${'Page' @ i18n}

The hint option can be used to provide a comment for translators, specifying the context in which the text is used:

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

The default source for the language is ‘resource’, meaning that the text gets translated to the same language as the content. This can be changed to ‘user’, meaning that the language is taken from the browser locale or from the locale of the logged-in user:

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

Providing an explicit locale overrides the source settings:

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

To embed variables into a translated string, the format option can be used:

1
${'Page {0} of {1}' @ i18n, format=[current, total]}

Array Join

By default, when displaying an array as text, HTL will display comma separated values (without spacing).

Use the join option to specify a different separator:

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

Display Context

The display context of a HTL expression refers to its location within the structure of the HTML page. For example, if the expression appears in place that would produce a text node once rendered, then it is said to be in a text context. If it is found within the value of an attribute, then it is said to be in an attribute context, and so forth.

With the exception of script (JS) and style (CSS) contexts, HTL will automatically detect the context of expressions and escape them appropriately, to prevent XSS security problems. In the case of scripts and CSS, the desired context behavior must be explicitly set. Additionally, the context behavior can also be explicitly set in any other case where an override of the automatic behavior is desired.

Here we have three variables in three different contexts: properties.link (uri context), properties.title(attribute context) and properties.text (text context). HTL will escape each of these differently in accordance with the security requirements of their respective contexts. No explicit context setting is required in normal cases such as this one:

<a href="${properties.link}" title="${properties.title}">${properties.text}</a>

 

To safely output markup (that is, where the expression itself evaluates to HTML), the html context is used:

<div>${properties.richText @ context='html'}</div>

 

Explicit context must be set for style contexts:

<span style="color: ${properties.color @ context='styleToken'};">...</span>

 

Explicit context must be set for script contexts:

<span onclick="${properties.function @ context='scriptToken'}();">...</span>

 

Escaping and XSS protection can also be turned off:

<div>${myScript @ context='unsafe'}</div>

 

HTL Block Statements

HTML Template Language (HTL) block statements are custom data attributes added directly to existing HTML. This allows easy and unobtrusive annotation of a prototype static HTML page, converting it to a functioning dynamic template without breaking the validity of the HTML code.

sly element

The <sly> element does not get displayed in the resulting HTML and can be used instead of the data-sly-unwrap. The goal of the <sly> element is to make it more obvious that the element is not outputted. If you want you can still use data-sly-unwrap.

<sly data-sly-test.varone="${properties.yourProp}"/>

 

As with data-sly-unwrap, try to minimize the use of this.

use

data-sly-use: Initializes a helper object (defined in JavaScript or Java) and exposes it through a variable.

Initialize a JavaScript object, where the source file is located in the same directory as the template. Note that the filename must be used:

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

 

Initialize a Java class, where the source file is located in the same directory as the template. Note that the classname must be used, not the file name:

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

 

Initialize a Java class, where that class is installed as part of an OSGi bundle. Note that its fully-qualified class name must be used:

<div data-sly-use.nav="org.example.Navigation">${nav.foo}</div>

 

Parameters can be passed to the initialization using options. Generally this feature should only be used by HTL code that is itself within a data-sly-template block:

<div data-sly-use.nav="${'navigation.js' @parentPage=currentPage}">${nav.foo}</div>

 

Initialize another HTL template that can then be called using data-sly-call:

<div data-sly-use.nav="navTemplate.html" data-sly-call="${nav.foo}"></div>

unwrap

data-sly-unwrap: Removes the host element from the generated markup while retaining its content. This allows the exclusion of elements that are required as part of HTL presentation logic but are not desired in the actual output.

However, this statement should be used sparingly. In general it is better to keep the HTL markup as close as possible to the intended output markup. In other words, when adding HTL block statements, try as much as possible to simply annotate the existing HTML, without introducing new elements.

For example, this

<p data-sly-use.nav="navigation.js">Hello World</p>

 

will produce

1
<p>Hello World</p>

Whereas this,

<p data-sly-use.nav="navigation.js" data-sly-unwrap>Hello World</p>

 

will produce

1
Hello World

It is also possible to conditionally unwrap an element:

<div class="popup" data-sly-unwrap="${isPopup}">content</div>

 

text

data-sly-text: Replaces the content of its host element with the specified text.

For example, this

<p>${properties.jcr:description}</p>

 

is equivalent to

<p data-sly-text="${properties.jcr:description}">Lorem ipsum</p>

 

Both will display the value of jcr:description as paragraph text. The advantage of the second method is that is allows the unobtrusive annotation of HTML while keeping the static placeholder content from the original designer.

attribute

data-sly-attribute: Adds attributes to the host element.

For example, this

<div title="${properties.jcr:title}"></div>

 

is equivalent to

<div title="Lorem Ipsum" data-sly-attribute.title="${properties.jcr:title}"></div>

 

Both will set the title attribute to the value of jcr:title. The advantage of the second method is that is allows the unobtrusive annotation of HTML while keeping the static placeholder content from the original designer.

 

Attributes are resolved left to right, with the rightmost instance of an attribute (either literal or defined via data-sly-attribute) taking precedence over any instances of the same attribute (defined either literally or via data-sly-attribute) defined to its left.

Note that an attribute (either literal or set via data-sly-attribute) whose value evaluates to the empty string will be removed in the final markup. The one exception to this rule is that a literal attribute set to a literal empty string will be preserved. For example,

<div class="${''}" data-sly-attribute.id="${''}"></div>

 

produces,

1
<div></div>

but,

<div class="" data-sly-attribute.id=""></div>

 

produces,

1
<div class=""></div>

To set multiple attributes, pass a map object hold key-value pairs corresponding to the attributes and their values. For example, assuming,

attrMap = {
    title: "myTitle",
    class: "myClass",
    id: "myId"
}

 

Then,

<div data-sly-attribute="${attrMap}"></div>

 

produces,

<div title="myTitle" class="myClass" id="myId"></div>

 

element

data-sly-element: Replaces the element name of the host element.

For example,

<h1 data-sly-element="${titleLevel}">text</h1>

Replaces the h1 with the value of titleLevel.

For security reasons, data-sly-element accepts only the following element names:

a abbr address article aside b bdi bdo blockquote br caption cite code col colgroup
data dd del dfn div dl dt em figcaption figure footer h1 h2 h3 h4 h5 h6 header i ins
kbd li main mark nav ol p pre q rp rt ruby s samp section small span strong sub
sup table tbody td tfoot th thead time tr u var wbr

 

To set other elements, XSS security must be turned off (@context=’unsafe’).

test

data-sly-test: Conditionally removes the host element and it’s content. A value of false removes the element; a value of true retains the element.

For example, the p element and its content will only be rendered if isShown is true:

<p data-sly-test="${isShown}">text</p>

 

The result of a test can be assigned to a variable that can be used later. This is usually used to construct “if else” logic, since there is no explicit else statement:

<p data-sly-test.abc="${a || b || c}">is true</p>
<p data-sly-test="${!abc}">or not</p>

 

The variable, once set, has global scope within the HTL file.

Following are some examples on comparing values:

<div data-sly-test="${properties.jcr:title == 'test'}">TEST</div>
<div data-sly-test="${properties.jcr:title != 'test'}">NOT TEST</div>
<div data-sly-test="${properties['jcr:title'].length > 3}">Title is longer than 3</div>
<div data-sly-test="${properties['jcr:title'].length >= 0}">Title is longer or equal to zero </div>
<div data-sly-test="${properties['jcr:title'].length > aemComponent.MAX_LENGTH}">
    Title is longer than the limit of ${aemComponent.MAX_LENGTH}
</div>

 

repeat

With data-sly-repeat you can repeat an element multiple times based on the list that is specified.

<div data-sly-repeat="${currentPage.listChildren}">${item.name}</div>

 

This works the same way as data-sly-list, except that you do not need a container element.

The following example shows that you can also refer to the item for attributes:

<div data-sly-repeat="${currentPage.listChildren}" data-sly-attribute.class="${item.name}">${item.name}</div>

 

list

data-sly-list: Repeats the content of the host element for each enumerable property in the provided object.

Here is a simple loop:

<dl data-sly-list="${currentPage.listChildren}">
    <dt>index: ${itemList.index}</dt>
    <dd>value: ${item.title}</dd>
</dl>

 

The following default variables are available within the scope of the list:

item: The current item in the iteration.

itemList: Object holding the following properties:

index: zero-based counter (0..length-1).

count: one-based counter (1..length).

firsttrue if the current item is the first item.

middletrue if the current item is neither the first nor the last item.

lasttrue if the current item is the last item.

oddtrue if index is odd.

eventrue if index is even.

Defining an identifier on the data-sly-list statement allows you to rename the itemList and item variables. item will become <variable> and itemList will become <variable>List.

<dl data-sly-list.child="${currentPage.listChildren}">
    <dt>index: ${childList.index}</dt>
    <dd>value: ${child.title}</dd>
</dl>

 

You can also access properties dynamically:

<dl data-sly-list.child="${myObj}">
    <dt>key: ${child}</dt>
    <dd>value: ${myObj[child]}</dd>
</dl>

 

resource

data-sly-resource: Includes the result of rendering the indicated resource through the sling resolution and rendering process.

A simple resource include:

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

 

Options allow a number of additional variants:

Manipulating the path of the resource:

<article data-sly-resource="${ @ path='path/to/resource'}"></article>
<article data-sly-resource="${'resource' @ prependPath='my/path'}"></article>
<article data-sly-resource="${'my/path' @ appendPath='resource'}"></article>

 

Add (or replace) a selector:

<article data-sly-resource="${'path/to/resource' @ selectors='selector'}"></article>

 

Add, replace or remove multiple selectors:

<article data-sly-resource="${'path/to/resource' @ selectors=['s1', 's2']}"></article>

 

Add a selector to the existing ones:

<article data-sly-resource="${'path/to/resource' @ addSelectors='selector'}"></article>

 

Remove some selectors from the existing ones:

<article data-sly-resource="${'path/to/resource' @ removeSelectors='selector1'}"></article>

 

Remove all selectors:

<article data-sly-resource="${'path/to/resource' @ removeSelectors}"></article>

 

Overrides the resource type of the resource:

<article data-sly-resource="${'path/to/resource' @ resourceType='my/resource/type'}"></article>

 

Changes the WCM mode:

<article data-sly-resource="${'path/to/resource' @ wcmmode='disabled'}"></article>

 

By default, the AEM decoration tags are disabled, the decorationTagName option allows to bring them back, and the cssClassName to add classes to that element.

<article data-sly-resource="${'path/to/resource' @ decorationTagName='span',
cssClassName='className'}"></article>

Note:

AEM offers clear and simple logic controling the decoration tags that wrap included elements. For details see Decoration Tag in the developing components documentation.

include

data-sly-include: Replaces the content of the host element with the markup generated by the indicated HTML template file (HTL, JSP, ESP etc.) when it is processed by its corresponding template engine. The rendering context of the included file will not include the current HTL context (that of the including file); Consequently, for inclusion of HTL files, the current data-sly-use would have to be repeated in the included file (In such a case it is usually better to use data-sly-template and data-sly-call)

A simple include:

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

 

JSPs can be included the same way:

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

 

Options let you manipulate the path of the file:

<section data-sly-include="${ @ path='path/to/template.html'}"></section>
<section data-sly-include="${'template.html' @ prependPath='my/path'}"></section>
<section data-sly-include="${'my/path' @ appendPath='template.html'}"></section>

 

You can also change the WCM mode:

<section data-sly-include="${'template.html' @ wcmmode='disabled'}"></section>

 

template & call

data-sly-template: Defines a template. The host element and its content are not output by HTL

data-sly-call: Calls a template defined with data-sly-template. The content of the called template (optionally parameterized) replaces the content of the host element of the call.

Define a static template and then call it:

<template data-sly-template.one>blah</template>
<div data-sly-call="${one}"></div>

 

Define a dynamic template and then call it with parameters:

<template data-sly-template.two="${ @ title}"><h1>${title}</h1></template>
<div data-sly-call="${two @ title=properties.jcr:title}"></div>

 

Templates located in a different file, can be initialised with data-sly-use. Note that in this case data-sly-use and data-sly-call could also be placed on the same element:

<div data-sly-use.lib="templateLib.html">
    <div data-sly-call="${lib.one}"></div>
    <div data-sly-call="${lib.two @ title=properties.jcr:title}"></div>
</div>

 

Template recursion is supported:

<template data-sly-template.nav="${ @ page}">
    <ul data-sly-list="${page.listChildren}">
        <li>
            <div class="title">${item.title}</div>
            <div data-sly-call="${nav @ page=item}" data-sly-unwrap></div>
        </li>
    </ul>
</template>
<div data-sly-call="${nav @ page=currentPage}" data-sly-unwrap></div>

 

i18n and locale objects

When you are using i18n and HTL, you can now also pass in custom locale objects.

${'Hello World' @ i18n, locale=request.locale}

 

URL manipulation

A new set of url manipulations is available.

See the following examples on their usage:

Adds the html extension to a path.

<a href="${item.path @ extension = 'html'}">${item.name}</a>

 

Adds the html extension and a selector to a path.

<a href="${item.path @ extension = 'html', selectors='products'}">${item.name}</a>

 

Adds the html extension and a fragment (#value) to a path.

<a href="${item.path @ extension = 'html', fragment=item.name}">${item.name}</a>

 

HTL Features Supported in AEM 6.3

The following new HTL features are supported in Adobe Experience Manager (AEM) 6.3:

Number/Date-formatting

AEM 6.3 supports native formatting of numbers and dates, without writing custom code. This also supports timezone and locale.

The following examples show that the format is specified first, then the value that needs formatting:

<h2>${ 'dd-MMMM-yyyy hh:mm:ss' @
           format=currentPage.lastModified,
           timezone='PST',
           locale='fr'}</h2>
<h2>${ '#.00' @ format=300}</h2>

 

data-sly-use with resources

This allows to get resources directly in HTL with data-sly-use and does not require to write code to get the resource.

For example:

<div data-sly-use.product=“/etc/commerce/product/12345”>
  ${ product.title }
</div>

 

Request-attributes

In the data-sly-include and data-sly-resource you can now pass requestAttributes in order to use them in the receiving HTL-script.

This allows you to properly pass-in parameters into scripts or components.

<sly data-sly-use.settings="com.adobe.examples.htl.core.hashmap.Settings"
        data-sly-include="${ 'productdetails.html' @ requestAttributes=settings.settings}" />

 

Java-code of the Settings class, the Map is used to pass in the requestAttributes:

public class Settings extends WCMUsePojo {
  // used to pass is requestAttributes to data-sly-resource
  public Map<String, Object> settings = new HashMap<String, Object>();
  @Override
  public void activate() throws Exception {
    settings.put("layout", "flex");
  }
}

 

For example, via a Sling-Model, you can consume the value of the specified requestAttributes.

In this example, layout is injected via the Map from the Use-class:

@Model(adaptables=SlingHttpServletRequest.class)
public class ProductSettings {
  @Inject @Optional @Default(values="empty")
  public String layout;
}

 

Fix for @extension

The @extension works in all scenarios in AEM 6.3, before you could have a result like http://www.adobe.com.html and also checks whether to add or not add the extension.

${ link @ extension = 'html' }

HTL Global Objects

Without having to specify anything, HTL provides access to all objects that were commonly available in JSP after including global.jsp. These objects are in addition to any that may be introduced through the Use-API.

Enumerable Objects

These objects provide convenient access to commonly used information. Their content can be accessed with the dot notation, and they can be iterated-through using data-sly-list or data-sly-repeat.

Variable Name Description
properties List of properties of the current Resource.
Backed by org.apache.sling.api.resource.ValueMap
pageProperties List of page properties of the current Page.
Backed by org.apache.sling.api.resource.ValueMap
inheritedPageProperties List of inherited page properties of the current Page.
Backed by org.apache.sling.api.resource.ValueMap

Java-backed Objects

Each of the following objects is backed by the corresponding Java object.

The most useful variables in the table below are highlighted in bold.

Variable Name Description
component com.day.cq.wcm.api.components.Component
componentContext com.day.cq.wcm.api.components.ComponentContext
currentDesign com.day.cq.wcm.api.designer.Design
currentNode javax.jcr.Node
currentPage com.day.cq.wcm.api.Page
currentSession javax.servlet.http.HttpSession
currentStyle com.day.cq.wcm.api.designer.Style
designer com.day.cq.wcm.api.designer.Designer
editContext com.day.cq.wcm.api.components.EditContext
log org.slf4j.Logger
out java.io.PrintWriter
pageManager com.day.cq.wcm.api.PageManager
reader java.io.BufferedReader
request org.apache.sling.api.SlingHttpServletRequest
resolver org.apache.sling.api.resource.ResourceResolver
resource org.apache.sling.api.resource.Resource
resourceDesign com.day.cq.wcm.api.designer.Design
resourcePage com.day.cq.wcm.api.Page
response org.apache.sling.api.SlingHttpServletResponse
sling org.apache.sling.api.scripting.SlingScriptHelper
slyWcmHelper com.adobe.cq.sightly.WCMScriptHelper
wcmmode com.adobe.cq.sightly.SightlyWCMMode
xssAPI com.adobe.granite.xss.XSSAPI

JavaScript-backed Objects

There are also objects available that are backed by JavaScript. However, as of AEM 6.2 these objects are still experimental and it is better to use the Java-backed objects, which allow to do the same.

HTL Use-API

The following table gives an overview of the pros and cons of each API.

Java Use-API JavaScript Use-API
Pros
  • faster
  • can be inspected with a debugger
  • easy to unit-test
  • can be modified by front-end developers
  • is located within the component, keeping the view logic of a component close to it’s corresponding template
Cons
  • cannot be modified by front-end developers
  • slower
  • no debugger (yet)
  • harder to unit-test

For page components, it is recommended to use a mixed model, where all model logic is located in Java, providing clear APIs that are agnostic to anything that happens in the view (i.e. within the components). AEM comes with great default models like the Page or the Resource API that should be able to cover most cases.

All view logic that is specific to a component should be placed within that component as JavaScript, because it belongs to that component.

Developer Tools

The following developer tools are available for HTL:

  • HTL Read Eval Print Loop
    A live execution environment for playing with the language, great for learning.
  • AEM Brackets extension
    An easy tool for front-end developers to work on AEM components.
  • AEM Eclipse extension
    A tool for back-end developers to create AEM projects and easily edit them.

Structure within the Repository AEM6.3

Caution:

You must not change anything in the /libs path. For configuration and other changes copy the item from /libs to /apps and make any changes within /apps.

  • /apps
    Application related; includes component definitions specific to your website. The components that you develop can be based on the out of the box components available at /libs/foundation/components.
  • /content
    Content created for your website.
  • /etc
    Tools section for detailed information.
  • /home
    User and Group information.
  • /libs
    Libraries and definitions that belong to the core of AEM. The sub-folders in /libs represent the out of the box AEM features as for example search or replication.  The content in /libs should not be modified as it affects the way AEM works. Features specific to your website should be developed under /apps .
  • /tmp
    Temporary working area.
  • /var
    Files that change and are updated by the system; such as audit logs, statistics, event-handling. The sub-folder /var/classes contains the java servlets in source and compiled forms that have been generated from the components scripts.

Sling Request Processing

Introduction to Sling

AEM is built using Sling, a Web application framework based on REST principles that provides easy development of content-oriented applications. Sling uses a JCR repository, such as Apache Jackrabbit, or in the case of AEM, the CRX Content Repository, as its data store.

The following diagram explains Sling script resolution:

chlimage_1

 

The following diagram explains all the hidden, but powerful, request parameters you can use when dealing with the SlingPostServlet, the default handler for all POST requests that gives you endless options for creating, modifying, deleting, copying and moving nodes in the repository.

chlimage_1

Sling is Content Centric

Sling is content-centric. This means that processing is focused on the content as each (HTTP) request is mapped onto content in the form of a JCR resource (a repository node):

  • the first target is the resource (JCR node) holding the content
  • secondly, the representation, or script, is located from the resource properties in combination with certain parts of the request (e.g. selectors and/or the extension)

RESTful Sling

Due to the content-centric philosophy, Sling implements a REST-oriented server and thus features a new concept in web application frameworks. The advantages are:

  • very RESTful, not just on the surface; resources and representations are correctly modelled inside the server
  • removes one or more data models
    • previously the following were needed: URL structure, business objects, DB schema;
    • this is now reduced to: URL = resource = JCR structure

URL Decomposition

In Sling, processing is driven by the URL of the user request. This defines the content to be displayed by the appropriate scripts. To do this, information is extracted from the URL.

If we analyze the following URL:

http://myhost/tools/spy.printable.a4.html/a/b?x=12

We can break it down into its composite parts:

protocol host content path selector(s) extension suffix param(s)
http:// myhost tools/spy .printable.a4. html / a/b ? x=12

protocol :  HTTP

 

host : Name of the website.

 

content path : Path specifying the content to be rendered. Is used in combination with

the extension; in this example they translate to tools/spy.html.

 

selector(s) : Used for alternative methods of rendering the content; in this example a printer-friendly version in A4 format.

extension : Content format; also specifies the script to be used for rendering.

suffix : Can be used to specify additional information.

param(s) : Any parameters required for dynamic content.

From URL to Content and Scripts

Using these principles:

  • the mapping uses the content path extracted from the request to locate the resource
  • when the appropriate resource is located, the sling resource type is extracted, and used to locate the script to be used for rendering the content

The figure below illustrates the mechanism used, which will be discussed in more detail in the following sections.

chlimage_1

With Sling, you specify which script renders a certain entity (by setting the sling:resourceType property in the JCR node). This mechanism offers more freedom than one in which the script accesses the data entities (as an SQL statement in a PHP script would do) as a resource can have several renditions.

Mapping requests to resources

The request is broken down and the necessary information extracted. The repository is searched for the requested resource (content node):

  • first Sling checks whether a node exists at the location specified in the request; e.g. ../content/corporate/jobs/developer.html
  • if no node is found, the extension is dropped and the search repeated; e.g. ../content/corporate/jobs/developer
  • if no node is found then Sling will return the http code 404 (Not Found).

Sling also allows things other than JCR nodes to be resources, but this is an advanced feature.

Locating the script

When the appropriate resource (content node) is located, the sling resource type is extracted. This is a path, which locates the script to be used for rendering the content.

The path specified by the sling:resourceType can be either:

  • absolute
  • relative, to a configuration parameter
    Relative paths are recommended by Adobe as they increase portability.

All Sling scripts are stored in subfolders of either /apps or /libs, which will be searched in this order.

A few other points to note are:

  • when the Method (GET, POST) is required, it will be specified in uppercase as according to the HTTP specification e.g. jobs.POST.esp (see below)
  • various script engines are supported:
    • .esp, .ecma: ECMAScript (JavaScript) Pages (server-side execution)
    • .jsp: Java Server Pages (server-side execution)
    • .java: Java Servlet Compiler (server-side execution)
    • .jst: JavaScript templates (client-side execution)

The list of script engines supported by the given instance of CQ are listed on the Felix Management Console (http://localhost:4502/system/console/config/slingscripting.txt).

 

Using the above example, if the sling:resourceType is hr/jobs then for:

  • GET/HEAD requests, and URLs ending in .html (default request types, default format)
    The script will be /apps/hr/jobs/jobs.esp; the last section of the sling:resourceType forms the file name.
  • POST requests (all request types excluding GET/HEAD, the method name must be uppercase)
    POST will be used in the script name.
    The script will be /apps/hr/jobs/jobs.POST.esp.
  • URLs in other formats, not ending with .html
    For example ../content/corporate/jobs/developer.pdf
    The script will be /apps/hr/jobs/jobs.pdf.esp; the suffix is added to the script name.
  • URLs with selectors
    Selectors can be used to display the same content in an alternative format. For example a printer friendly version, an rss feed or a summary.
    If we look at a printer friendly version where the selector could be print; as in ../content/corporate/jobs/developer.print.html
    The script will be /apps/hr/jobs/jobs.print.esp; the selector is added to the script name.
  • If no sling:resourceType has been defined then:
    • the content path will be used to search for an appropriate script (if the path based ResourceTypeProvider is active).
      For example, the script for ../content/corporate/jobs/developer.html would generate a search in /apps/content/corporate/jobs/.
    • the primary node type will be used.
  • If no script is found at all then the default script will be used.
    The default rendition is currently supported as plain text (.txt), HTML (.html) and JSON (.json), all of which will list the node’s properties (suitably formatted). The default rendition for the extension .res, or requests without a request extension, is to spool the resource (where possible).
  • For http error handling (codes 403 or 404) Sling will look for a script at either:
    • the location /apps/sling/servlet/errorhandler for customized scripts
    • or the location of the standard scripts /libs/sling/servlet/errorhandler/403.esp, or 404.esp respectively.

If multiple scripts apply for a given request, the script with the best match is selected. The more specific a match is, the better it is; in other words, the more selector matches the better, regardless of any request extension or method name match.

For example, consider a request to access the resource
/content/corporate/jobs/developer.print.a4.html
of type
sling:resourceType=”hr/jobs”

Assuming we have the following list of scripts in the correct location:

  1. GET.esp
  2. jobs.esp
  3. html.esp
  4. print.esp
  5. print.html.esp
  6. print/a4.esp
  7. print/a4/html.esp
  8. print/a4.html.esp

Then the order of preference would be (8) – (7) – (6) – (5) – (4) – (3) – (2) – (1).

In addition to the resource types (primarily defined by the sling:resourceType property) there is also the resource super type. This is generally indicated by the sling:resourceSuperType property. These super types are also considered when trying to find 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:

  • by the sling:resourceSuperType property of the resource.
  • by the sling:resourceSuperType property of the node to which the sling:resourceType points.

For example:

  • /
    • a
    • b
      • sling:resourceSuperType = a
    • c
      • sling:resourceSuperType = b
    • x
      • sling:resourceType = c
    • y
      • sling:resourceType = c
      • sling:resourceSuperType = a

The type hierarchy of /x is [ c, b, a, <default>] while for /y the hierarchy is [ c, a, <default>] because /y has the sling:resourceSuperType property whereas /x does not and therefore its supertype is taken from its resource type.

Sling Scripts cannot be called directly

Within Sling, scripts cannot be called directly as this would break the strict concept of a REST server; you would mix resources and representations.

If you call the representation (the script) directly you hide the resource inside your script, so the framework (Sling) no longer knows about it. Thus you lose certain features:

  • automatic handling of http methods other than GET, including:
    • POST, PUT, DELETE which are handled with a sling default implementation
    • the POST.jsp script in your sling:resourceType location
  • your code architecture is no longer as clean nor as clearly structured as it should be; of prime importance for large-scale development

Sling API

This uses the Sling API package, org.apache.sling.*, and tag libraries.

Referencing existing elements using sling:include

A final consideration is the need to reference existing elements within the scripts.

More complex scripts (aggregating scripts) might need to access multiple resources (for example navigation, sidebar, footer, elements of a list) and do so by including the resource.

To do this you can use the sling:include(“/<path>/<resource>”) command. This will effectively include the definition of the referenced resource, as in the following statement which references an existing definition for rendering images:

%><sling:includeresourceType="geometrixx/components/image/img"/><%

Using Sling Adapters

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.

For example to translate a Resource object to the corresponding Node object, you can simply do:

Node node = resource.adaptTo(Node.class);

 

Null Return Value

adaptTo() can return null.

There are various reasons for this, including:

  • the implementation does not support the target type
  • an adapter factory handling this case is not active (eg. due to missing service references)
  • internal condition failed
  • service is not available

It is important that you handle the null case gracefully. For jsp renderings it might be acceptable to have the jsp fail if that will result in an empty piece of content.

Caching

To improve performance, implementations are free to cache the object returned from a obj.adaptTo() call. If the obj is the same, the returned object is the same.

This caching is performed for all AdapterFactory based cases.

However, there is no general rule – the object could be either a new instance or an existing one. This means that you cannot rely on either behavior. Hence it is important, especially inside AdapterFactory, that objects are reusable in this scenario.

How it works

There are various ways that Adaptable.adaptTo() can be implemented:

  • By the object itself; implementing the method itself and mapping to certain objects.
  • By an AdapterFactory, which can map arbitrary objects.
    The objects must still implement the Adaptable interface and must extend SlingAdaptable (which passes the adaptTo call to a central adapter manager).
    This allows hooks into the adaptTo mechanism for existing classes, such as Resource.
  • A combination of both.

For the first case, the javadocs can state what adaptTo-targets are possible. However, for specific subclasses such as the JCR-based Resource, often this is not possible. In the latter case, implementations of AdapterFactory are typically part of the private classes of a bundle and thus not exposed in a client API, nor listed in javadocs. Theoretically, it would be possible to access all AdapterFactory implementations from the OSGi service runtime and look at their “adaptables” (sources and targets) configurations, but not to map them to each other. In the end, this depends on the internal logic, which must be documented. Hence this reference.

Reference

Sling

Resource adapts to:

Node If this is a JCR-node-based resource or a JCR property referencing a node.
Property If this is a JCR-property-based resource.
Item If this is a JCR-based resource (node or property).
Map Returns a map of the properties, if this is a JCR-node-based resource (or other resource supporting value maps).
ValueMap Returns a convenient-to-use map of the properties, if this is a JCR-node-based resource (or other resource supporting value maps). Can also be achieved (more simply) by using
ResourceUtil.getValueMap(Resource) (handles null case, etc.).
InheritanceValueMap Extension of ValueMap which allows the hierarchy of resources to be taken into account when looking for properties.
PersistableValueMap If this is a JCR-node-based resource and the user has permissions to modify properties on that node.
Note: multiple persistable maps do not share their values.
InputStream Returns the binary content of a “file” resource (if this is a JCR-node-based resource and the node type is nt:file or nt:resource; if this is a bundle resource; file content if this is a file system resource) or the data of a binary JCR property
resource.
URL Returns a URL to the resource (repository URL of this node if this is a JCR-node-based resource; jar bundle URL if this is a bundle resource; file URL if this is a file system resource).
File If this is a file system resource.
SlingScript If this resource is a script (e.g. jsp file) for which a script engine is registered with sling.
Servlet If this resource is a script (e.g. jsp file) for which a script engine is registered with sling or if this is a servlet resource.
Authorizable
(Jackrabbit)
If this is a an authorizable resource (from the
AuthorizableResourceProvider in org.apache.sling.jackrabbit.usermanager, under /system/userManager).
String
Boolean
Long
Double
Calendar
Value
String[]
Boolean[]
Long[]
Calendar[]
Value[]
Returns the value(s) if this is a JCR-property-based resource (and the value fits).
LabeledResource If this is a JCR-node-based resource.
Page If this is a JCR-node-based resource and the node is a cq:Page (or cq:PseudoPage).
Component If this is a cq:Component node resource.
Design If this is a design node (cq:Page, typically under
/etc/designs).
Template If this is a cq:Template node resource.
Blueprint If this is a cq:Page node resource (more specific checks possible in the future).
Asset If this is a dam:Asset node resource.
Rendition If this is a dam:Asset rendition (nt:file under the rendition folder of a dam:Assert)
Tag If this is a cq:Tag node resource.
Preferences If this is a cq:Preferences node resource for a valid user/group.
Profile If this is the profile below a user/group node (eg.
cq/security/components/profile).
UserManager Based on the JCR session if this is a JCR-based resource and the user has permissions to access the UserManager.
Authorizable
(cq-security)
This is a authorizable home node.
User
(cq-security)
If this is a user home node.
PrivilegeManager
SimpleSearch Searches below the resource (or use setSearchIn()) if this is a JCR-based resource.
WorkflowStatus Workflow status for the given page/workflow payload node.
ReplicationStatus Replication status for the given resource or its jcr:content subnode (checked first).
ConnectorResource Returns an adapted connector resource for certain types, if this is a JCR-node-based resource.
Config If this is a cq:ContentSyncConfig node resource.
ConfigEntry If this is below a cq:ContentSyncConfig node resource.

ResourceResolver adapts to:

Session The request’s JCR session, if this is a JCR-based resource resolver (default).
PageManager
ComponentManager
Designer
AssetManager Based on the JCR session, if this is a JCR-based resource resolver.
TagManager Based on the JCR session, if this is a JCR-based resource resolver.
UserManager Based on the JCR session, if this is a JCR-based resource resolver, and if the user has permissions to access the UserManager.
Authorizable The current user.
User The current user.
PrivilegeManager
Preferences Preferences of the current user (based on JCR session if this is a JCR-based resource resolver).
PreferencesService
PinManager
QueryBuilder
Externalizer For externalizing absolute URLs, even with out the request object.

SlingHttpServletRequest adapts to:

No targets yet, but implements Adaptable and could be used as source in a custom AdapterFactory.

ContentHandler
(XML)
If this is a sling rewriter response.

WCM

Page adapts to:

Resource Resource of the page.
LabeledResource Labeled resource (== this).
Node Node of the page.
Everything that the page’s resource can be adapted to.

Component adapts to:

Resource Resource of the component.
LabeledResource Labeled resource (== this).
Node Node of the component.
Everything that the component’s resource can be adapted to.

Template adapts to:

Resource
Resource of the template.
LabeledResource Labeled resource (== this).
Node Node of this template.
Everything that the template’s resource can be adapted to.

Security

AuthorizableUser and Group adapt to:

Node Returns the user/group home node.
ReplicationStatus Returns the replication status for the user/group home node.

DAM

Asset adapts to:

Resource Resource of the asset.
Node Node of the asset.
Everything that the asset’s resource can be adapted to.

Tagging

Tag adapts to:

Resource Resource of the tag.
Node Node of the tag.
Everything that the tag’s resource can be adapted to.

Other

Furthermore Sling / JCR / OCM also provides an AdapterFactory for custom OCM (Object Content Mapping) objects.

 

Java Content Repository

The Java Content Repository (JCR) standard, JSR 283, specifies a vendor-independent and implementation-independent way to access content bi-directionally on a granular level within a content repository.

Specification lead is held by Adobe Research (Switzerland) AG.

The JCR API 2.0 package, javax.jcr.* is used for the direct access and manipulation of repository content.

Web Console AEM6.3

The Web console in AEM is based on the Apache Felix Web Management Console. Apache Felix is a community effort to implement the OSGi R4 Service Platform, which includes the OSGi framework and standard services.

Note:

On the Web console any descriptions that mention default settings relate to Sling defaults.

AEM has its own defaults and so the defaults set might differ from those documented on the console.

The Web console offers a selection of tabs for maintaining the OSGi bundles, including:

  • Configuration: used for configuring the OSGi bundles, and is therefore the underlying mechanism for configuring AEM system parameters
  • Bundles: used for installing bundles
  • Components: used for controlling the status of components required for AEM

Any changes made are immediately applied to the running system. No restart is required.

The console can be accessed from ../system/console; for example:

    http://localhost:4502/system/console/components

Configuration

The Configuration tab is used for configuring the OSGi bundles, and is therefore the underlying mechanism for configuring AEM system parameters.

The Configuration tab can be accessed by :

There are two types of configurations available from the drop down lists on this screen:

  • Configurations
    Allows you to update the existing configurations. These have a Persistent Identity (PID) and can be either:

    • standard and integral to AEM; these are required, if deleted the values return to the default settings.
    • instances created from Factory Configurations; these instances are created by the user, deletion removes the instance.
  • Factory Configurations
    Allows you to create an instance of the required functionality object.
    This will be allocated a Persistent Identity and then listed in the Configurations drop down list.

You can then update the parameters as required and:

  • Save
    Save the changes made.
    For a Factory Configuration this will create a new instance with a Persistent Identity. The new instance will then be listed under Configurations.
  • Reset
    Reset the parameters shown on screen to those saved last.
  • Delete
    Delete the current configuration. If standard, the parameters are returned to the default settings. If created from a Factory Configuration, then the specific instance is deleted.
  • Unbind
    Unbind the current configuration from the bundle.
  • Cancel
    Cancel any current changes.

Bundles

The Bundles tab is the mechanism for installing the OSGi bundles required for AEM. The tab can be accessed by either of the following methods:

Using this tab you can:

  • Install or Update
    You can Browse to find the file containing your bundle and specify whether it should Start immediately and at which Start Level.
  • Reload
    Refreshes the list displayed.
  • Refresh Packages
    This will check the references of all packages and refresh as necessary.
    For example, after an update both the old and new version may still be running due to prior references. This option will check and move all references to the new version, allowing the old version to stop.
  • Start
    Starts a bundle according to the start level specified.
  • Stop
    Stops the bundle.
  • Uninstall
    Uninstalls the bundle from the system.
  • see the status
    The list specifies the current status of the bundle; clicking on the name of a specific bundle with show further information.

Note:

After Update it is recommended to perform a Refresh Packages.

Components

The Components tab allows you to Enable and/or Disable the various components. It can be accessed by either:

 

A list of components will be shown. Various icons are available to enable you to enable, disable or (where appropriate) open configuration details for a specific component.

Clicking on the name of a particular component will display further information on its status. Here you can also enable, disable or reload the component.

Note:

Enabling, or disabling, a component will only apply until AEM/CRX is restarted.

The start state is defined within the component descriptor, which is generated during development and stored in the bundle at bundle creation time.

OSGI in AEM6.3

OSGI is a modular programming approach. Application can be divided into modules or bundles. Bundle will be JAR file + Metadata.

OSGI uses Apache Felix Implementation.

All Bundles are deployed on Felix container.

Every bundle has its own life cycle. i.e., it’s independent. Can be redeploy without affecting other bundle.

Each Bundle has its own class loader. Which allows developers to start and stop each bundle separately.

OSGI supports multiple version of bundle.

AEM works with the inbuilt bundles for separate functionalities

Bundles are stored under cr-quickstart/launchpad/felix.

All the OSGI configurations are stored under (/apps/sling/config or /apps/system/config) by default. The configuration will be saved as a paragraph property jcr:data in binary(non-readable format) on respective node.

You can manage the configuration settings for such bundles by either:

Adobe CQ Web console

The Web Console is the standard interface for OSGi configuration. It provides a UI for editing the various properties, where possible values can be selected from predefined lists.

As such it is the easiest method to use.

Any configurations made with the Web Console are applied immediately and applicable to the current instance, irrespective of the current run mode, or any subsequent changes to the run mode.

content-nodes (sling:osgiConfig) in the repository

This requires manual configuration using CRXDE Lite.

Due to the naming conventions of the sling:OsgiConfig nodes, you can tie the configuration to a specific run mode. You can even save configurations for more than one run mode in the same repository.

Any appropriate configurations are applied immediately (dependent on the run mode).

Basic SCR Annotation used for developing a component or service in osgi are:-

@Component – defines the class as a component.

@Service – defines the service interface that is provided by the component.

@Reference – injects a service into the component.

@Property – defines a property that can be used in the class.

Differences between package and bundle

Package: A Package is a zip file that contains the content in the form of a file-system serialization (called “vault” serialization) that displays the content from the repository as an easy-to-use-and-edit representation of files and folders. Packages can include content and project-related data.

Bundle: Bundle is a tightly coupled, dynamically loadable collection of classes, jars, and configuration files that explicitly declare their external dependencies (if any).

Difference between OSGi bundle and Normal Jar file

OSGi bundles are jar files with metadata inside. Much of this metadata is in the jar’s manifest, found at META-INF/MANIFEST.MF. This metadata, when read by an OSGi runtime container, is what gives the bundle its power.

With OSGi, just because a class is public doesn’t mean you can get to it. All bundles include an export list of package names, and if a package isn’t in the export list, it doesn’t exist to the outside world. This allows developers to build an extensive internal class hierarchy and minimize the surface area of the bundle’s API without abusing the notion of package-private visibility. A common pattern, for instance, is to put interfaces in one package and implementations in another, and only export the interface package.

All OSGi bundles are given a version number, so it’s possible for an application to simultaneously access different versions of the same bundle (eg: junit 3.8.1 and junit 4.0.). Since each bundle has it’s own class-loader, both bundles classes can coexist in the same JVM.

OSGi bundles declare which other bundles they depend upon. This allows them to ensure that any dependencies are met before the bundle is resolved. Only resolved bundles can be activated. Because bundles have versions, versioning can be included in the dependency specification, so one bundle can depend on version junit version 3.8.1 and another bundle depend on junit version 4.0.

In OSGi bundle, there will be an Activator.java class in OSGi which is an optional listener class to be notified of bundle start and stop events.
Life cycle of OSGI[Open Systems Gateway initiative] bundle

OSGi is a framework which allows modular development of applications using java. A large application can be constructed using small reusable components(called bundles in terms of OSGi) each of which can be independently started, stopped, and also can be configured dynamically while running without requiring a restart.

Following are the states of OSGI life cycle:

Installed – The bundle has been successfully installed.

Resolved – All Java classes that the bundle needs are available. This state indicates that the bundle is either ready to be started or has stopped.

Starting – The bundle is being started, the BundleActivator.start method will be called, and this method has not yet returned. When the bundle has an activation policy, the bundle will remain in the STARTING state until the bundle is activated according to its activation policy.

Active – The bundle has been successfully activated and is running; its Bundle Activator start method has been called and returned.

Stopping – The bundle is being stopped. The BundleActivator.stop method has been called but the stop method has not yet returned.

Uninstalled – The bundle has been uninstalled. It cannot move into another state.

Service

An OSGi service is a java object instance, registered into an OSGi framework with a set of properties. Any java object can be registered as a service, but typically it implements a well-known interface.
The client of a service is always an OSGi bundle, i.e. a piece of java code possible to start via the BundleActivator interface.
Each bundle may register zero or more services. Each bundle may also use zero or more services. There exists no limit on the number of services, more than the ones given by memory limits or java security permissions.

Service Factory

An OSGi service factory is a special class ServiceFactory, which can create individual instances of service objects for different bundles. Sometimes a service needs to be differently configured depending on which bundle uses the service. For example, the log service needs to be able to print the logging bundle’s id, otherwise the log would be hard to read.

Get session in servlet

We can get session from SlingHttpServletRequest.

Session session = slingHttpServletRequest.getResourceResolver().adaptTo(Session.class)

From ResourceResolverFactory,

Session session = resolver.adaptTo(Session.class);

SlingSafeMethodsServlet – Helper base class for read-only Servlets used in Sling. This base class is actually just a better implementation of the Servlet API HttpServlet class which accounts for extensibility. So extensions of this class have great control over what methods to overwrite. It supports GET, HEAD, OPTIONS etc methods.

SlingAllMethodsServlet – Helper base class for data modifying Servlets used in Sling. This class extends the SlingSafeMethodsServlet by support for the POST, PUT and DELETE methods.

OSGI

This architecture allows you to extend Sling with application specific modules. Sling, and therefore CQ5, uses the Apache Felix implementation of OSGI (Open Services Gateway initiative) .They are both collections of OSGi bundles running within an OSGi framework.

This enables you to perform the following actions on any of the packages within your installation:

  • install
  • start
  • stop
  • update
  • uninstall
  • see the current status
  • access more detailed information (e.g. symbolic name, version, location, etc) about the specific bundles

 

Each OSGi Component is contained in one of the various bundles.

You can manage the configuration settings for such bundles by either:

  • using the Adobe CQ Web console
  • using configuration files
  • configuring content-nodes (sling:OsgiConfig) in the repository

OSGi Configuration with the Web Console

The Web console in AEM provides a standardized interface for configuring the bundles. The Configuration tab is used for configuring the OSGi bundles, and is therefore the underlying mechanism for configuring AEM system parameters.

Any changes made are immediately applied to the relevant OSGi configuration, no restart is required.

Access the Configuration tab of the Web Console by either:

OSGi Configuration with configuration files

Configuration changes made using the Web Console are persisted in the repository as configuration files (.config) under:

    /apps

 

These can be included in content packages and re-used on other instances.

example : apps/system/config/org.apache.felix.webconsole.internal.servlet.OsgiManager.config

You can open this file to view your changes, but to avoid typing errors it is recommended to make actual changes with the console.

OSGi Configuration in the Repository

In addition to using the web console, you can also define configuration details in the repository. This allows you to easily configure your differing run modes.

These configurations are made by creating sling:OsgiConfig nodes in the repository for the system to reference. These nodes mirror the OSGi configurations, and form a user interface to them. To update the configuration data you update the node properties.

 

If you modify the configuration data in the repository the changes are immediately applied to the relevant OSGi configuration as if the changes had been 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/.

As the same configuration parameter can be located in several places, the system:

  • searches for all nodes of type sling:OsgiConfig
  • filters according to service name
  • filters according to run mode

Creating the Configuration in the Repository

To actually add the new configuration to the repository:

  • Use CRXDE Lite to navigate to:

        /apps/<yourProject>

  • If not already existing, create the config folder (sling:Folder):

    • config – applicable to all run modes
    • config.<run-mode> – specific to a particular run mode
  • Under this folder create a node:

    • Type: sling:OsgiConfig
    • Name: the persistent identity (PID);
      for example for AEM WCM Version Manager use com.day.cq.wcm.core.impl.VersionManagerImpl

    Note:

    When making a Factory Configuration append -<identifier> to the name.

    As in: org.apache.sling.commons.log.LogManager.factory.config-<identifier>

    Where <identifier> is replaced by free text that you (must) enter to identify the instance (you cannot omit this information); for example:

    org.apache.sling.commons.log.LogManager.factory.config-MINE

  • For each parameter that you want to configure, create a property on this node:

    • Name: the parameter name as shown in the Web console; the name is shown in brackets at the end of the field description. For example, for Create Version on Activation use versionmanager.createVersionOnActivation
    • Type: as appropriate.
    • Value: as required.

    You only need to create properties for the parameters that you want to configure, others will still take the default values as set by AEM.

  • Save all changes.

    Changes are applied as soon as the node is updated by restarting the service (as with changes made in the Web console).

    Configuration Details

    Resolution Order at Startup

     The following order of precedence is used:
    1. Repository nodes under /apps/*/config….either with type sling:OsgiConfig or property files.
    2. Repository nodes with type sling:OsgiConfig under /libs/*/config…. (out-of-the-box definitions).
    3. Any .config files from <cq-installation-dir>/crx-quickstart/launchpad/config/…. on the local file system.

    This means that a generic configuration in /libs can be masked by a project specific configuration in /apps.

    Resolution Order at Runtime

    Configuration changes made while the system is running trigger a reload with the modified configuration.

    Then the following order of precedence applies:

    1. Modifying a configuration in the Web console will take immediate effect as it takes precedence at runtime.
    2. Modifying a configuration in /apps will take immediate effect.
    3. Modifying a configuration in /libs will take immediate effect, unless it is masked by a configuration in /apps.

    Resolution of multiple Run Modes

    For run mode specific configurations, multiple run modes can be combined. For example, you can create configuration folders in the following style:

    /apps/*/config.<runmode1>.<runmode2>/

    Configurations in such 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 author,dev,emea, configuration nodes in /apps/*/config.emea/apps/*/config.author.dev/ and /apps/*/config.author.emea.dev/ will be applied, while configuration nodes in /apps/*/config.author.asean/ and /config/author.dev.emea.noldap/ will not be applied.

    If multiple configurations for the same PID are applicable, the configuration with the highest number of matching run modes is applied.

    For example, if an instance was started with the run modes author,dev,emea, and both /apps/*/config.author/ and /apps/*/config.emea.author/ define a configuration for
    com.day.cq.wcm.core.impl.VersionManagerImpl, the configuration in/apps/*/config.emea.author/ will be applied.

    This rule’s granularity is at a PID level.
    You cannot define some properties for the same PID in/apps/*/config.author/ and more specific ones in /apps/*/config.emea.author/ for the same PID.
    The configuration with the highest number of matching run modes will be effective for the entier PID.

    Standard Configurations

    The following list shows a small selection of the configurations available (in a standard installation) in the repository:

    • Author – AEM WCM Filter:
      libs/wcm/core/config.author/com.day.cq.wcm.core.WCMRequestFilter
    • Publish – AEM WCM Filter:
      libs/wcm/core/config.publish/com.day.cq.wcm.core.WCMRequestFilter
    • Publish – AEM WCM Page Statistics:
      libs/wcm/core/config.publish/com.day.cq.wcm.core.stats.PageViewStatistics

    Note:

    As these configurations reside in /libs they must not be edited directly, but copied to your application area (/apps) before customization.

    To list all configuration nodes in your instance, use the Query functionality in CRXDE Lite to submit the following SQL query:

    select * from sling:OsgiConfig

    Configuration Persistence

    • If you change a configuration through the Web console, it is (usually) written into the repository at:
      /apps/{somewhere

      • By default {somewhere} is system/config so the configuration is written to
        /apps/system/config
      • However, if you are editing a configuration which initially came from elsewhere in the repository: for example:
        /libs/foo/config/someconfig
        Then the updated configuration is written under the original location; for example:
        /apps/foo/config/someconfig
    • Settings that are changed by admin are saved in *.config files under:
      /crx-quickstart/launchpad/config

      • This is the private data area of the OSGi configuration admin and holds all configuration details specified by admin, regardless how they entered the system.
      • This is an implementation detail and you must never edit this directory directly.
      • However, it is useful to know the location of these configuration files so that copies can be taken for backup and/or multiple installation:
        • Apache Felix OSGi Management Console
          ../crx/org/apache/felix/webconsole/internal/servlet/OsgiManager.config
        • CRX Sling Client Repository
          ../com/day/crx/sling/client/impl/CRXSlingClientRepository/<pid-nr>.config

    Caution:

    You must never edit the folders or files under:

        /crx-quickstart/launchpad/config

    What is a Service

    The classical view of a service is nothing but work done for another part of AEM. So is it similar to a method call? The answer is no. How does a service differ from a method call?

    A service implies a contract between the provider of the service and its consumers. Consumers typically are not worried about the exact implementation behind a service (or even who provides it) as long as it follows the agreed contract, suggesting that services are to some extent substitutable. Using a service also involves a form of discovery or negotiation, implying that each service has a set of identifying features.

    What is a Component

    An AEM back-end component refers to managing the life cycle of a class in an OSGi environment. All OSGi services should be a component so that AEM handles the life cycle of a service. For example, the AEM handles when the component is activated, stopped, and so on.

    How to write an AEM Service

    You can write an AEM service  by developing a Java interface and implementation class. The implementation class uses the @Component and @Service annotations.

    How declarative services works in AEM

    AEM comes with a component framework called declarative services. OSGi bundles contain configuration files located at: OSGI-INF/servicecomponents.xml. A configuration file looks like the following illustration.

    xml


    This is a configuration file that an OSGi bundle understands. This file is populated by using SCR annotations (for example, @Service) in the implementation class.

    What is Dependency Injection

    By using Dependency Injection within AEM, you can inject an AEM Service into another service. You perform this task by using a @Reference annotation. For example, consider an AEM DataSourcePool. You can inject that into another AEM service so that the service can perform SQL operations on a database.

    What is service ranking

    There can be multiple implementations for a given interface which means there can be multiple implementations for a service. If there are multiple implementations and the consumer is interested about a particular implementation, there are ways to select it by using OSGi properties.

    If nothing is specified, then the implementation with the highest ranking is selected. In some scenarios, there is a chance of having the same service ranking in that case OSGi considers service identifier. Because the service identifier is an increasing number assigned by the framework, lower identifiers are associated with older services. So if multiple services have equal ranks, the framework effectively chooses the oldest service, which guarantees some stability and provides an affinity to existing services.

    The following code shows an implementation example. There is interface named HelloWorld which contains the sayHellomethod.  The implementation class is named HelloWorldImpl1 and contains an implementation sayHello method with service rankings 1000 and 1001 respectively. Now when this service is referenced the service with the highest ranking is selected.

    public interface HelloWorld {
        String sayHello();
    }

     

    The following Java code represents the implementation class.

    @Component
    @Service
    @Property(name="service.ranking", intValue=1000)
    public class HelloWorldImpl1 implements HelloWorld {
    @Override
        public String sayHello() {
            return "This message is from Hello service 1";
        }
    }

     

    The following represents the other implementation class.

    @Component
    @Service
    @Property(name="service.ranking", intValue=1001)
    public class HelloWorldImpl2 implements HelloWorld {
        @Override
        public String sayHello() {
            return "This message is from Hello service 2";
        }
    }

     

    This raises a question what if new service implementation called HelloServiceImpl3 with the service ranking 1002 is deployed. In this case all the services which are bind to the HelloWorldImpl2 until they are reinitialized. The easiest way to bind to new service is restart the component which is using that service or restart the bundle.

    What is Cardinality while referencing a service

    There can be multiple implementations of a service. So while referencing cardinality plays two roles in the Declarative Services specification:
    1. Optionality: Cardinality values starting with 0 are treated as optional, whereas values starting with 1 are treated as mandatory.

    2. Aggregation: Cardinality values ending with 1 are treated as a dependency on a single service object of the specified type, whereas values ending in n are treated as a dependency on all available service objects of the specified type. This leads to four different possible values:

    • 0..1 – Optional and unary
    • 1..1 – Mandatory and unary (Default)
    • 0..n – Optional and multiple
    • 1..n – Mandatory and multiple

    3. Optional Vs Mandatory:  If the Optionality value is “0” then the service, which is referencing is active even if the referenced service isn’t available. If the value is “1” then the referencing service is active if and only if the referenced service is active.

    Unary Vs Multiple: If the aggregation value is “1” then it is bounded to singular dependency. This service selection again depends on service ranking or service identifier. If the value is” n” then it is requesting for aggregate dependency this will take all the service implementations. This is a special case and should be handled differently with the code as shown in the below code snippet.

    @Reference(cardinality= ReferenceCardinality.MANDATORY_MULTIPLE,
    bind="bind",unbind="unbind",
    referenceInterface=HelloWorld.class,
    policy=ReferencePolicy.DYNAMIC)
        List<HelloWorld> helloWorldImplList;
        
        protected void bind(HelloWorld helloWorld){
            if(helloWorldImplList == null){
                helloWorldImplList = new ArrayList<HelloWorld>();
    }
            helloWorldImplList.add(helloWorld);
        }
        protected void unbind(HelloWorld helloWorld){
            helloWorldImplList.remove(helloWorld);
        }

     

    In the above code bind and unbind methods, there are multiple calls. Each call is a helloWorld implementation that was found in the service registry that matched HelloWorld and all the implementation classes are added to a list. This list can be used to retrieve all the implementation classes.

    What is reference policy while referencing a service?

    AEM OSGi bundles are dynamic (which means that services can come and go on the fly). Therefore a service might be deregistered while it’s been referenced or might come back at any moment.To handle this possible situation, OSGi provides two types of reference policies:

    • Static (default)
    • Dynamic

    Static Policy

    When a  static service is been referenced, a new instance is injected. This means

    before using this referenced service, if it is being unregistered from the
    service registry, SCR by default does not dynamically change the value of a
    service reference. Instead, it discards the component instance and creates a
    new instance (So on the fly it had replaced implementation class with the null
    value). If the component is also published as a service then the service
    registration is removed and replaced.

    Consider the following code example.

    Code

    Assume that HelloWorldImpl2 component is stopped. As soon as the component is stopped, it discarded the component instance and created a new one. Now what if the referenced service comes back?
    Because it’s a static reference policy this component cannot bind newly created service reference. This component can be recreated to get it bind to the new service.

    Dynamic Policy

     Dynamic policy simply informs SCR that our component is capable of being updated with changing references. But code should handle synchronization problems and should be careful while doing this.If a service reference is having dynamic policy then ideally we should have a bind and unbind methods. A bind method will be called and a reference is injected as a parameter. So inside the bind method reference has to be assigned to the local variable.

    @Reference(bind = “bind”, unbind = “unbind”, policy =ReferencePolicy.DYNAMIC, cardinality=ReferenceCardinality.OPTIONAL_UNARY) HelloWorldhelloWorld;

    LOG.info(“—————–binding———————“); this.helloWorld = helloWorld; }

    Now even though a referenced service goes off as we haveassigned it to a local variable (helloWorld) it will be still exist until thecomponent gets destroyed.Now what if the referenced service comes back?Because it’s a dynamic reference policy, this componentbinds to the new service on the fly.

    Layering

    The OSGi has a layered model that is depicted in the following figure.

    layering-osgi

    The following list contains a short definition of the terms:

    • Bundles – Bundles are the OSGi components made by the developers.
    • Services – The services layer connects bundles in a dynamic way by offering a publish-find-bind model for plain old Java objects.
    • Life-Cycle – The API to install, start, stop, update, and uninstall bundles.
    • Modules – The layer that defines how a bundle can import and export code.
    • Security – The layer that handles the security aspects.
    • Execution Environment – Defines what methods and classes are available in a specific platform.

    These concepts are more extensively explained in the following sections.

    Modules

    The fundamental concept that enables such a system is modularity. Modularity, simplistically said, is about assuming less. Modularity is about keeping things local and not sharing. It is hard to be wrong about things you have no knowledge of and make no assumptions about them. Therefore, modularity is at the core of the OSGi specifications and embodied in the bundleconcept. In Java terms, a bundle is a plain old JAR file. However, where in standard Java everything in a JAR is completely visible to all other JARs, OSGi hides everything in that JAR unless explicitly exported. A bundle that wants to use another JAR must explicitly import the parts it needs. By default, there is no sharing.

    Though the code hiding and explicit sharing provides many benefits (for example, allowing multiple versions of the same library being used in a single VM), the code sharing was only there to support OSGi services model. The services model is about bundles that collaborate.

    Services

    The reason we needed the service model is because Java shows how hard it is to write collaborative model with only class sharing. The standard solution in Java is to use factoriesthat use dynamic class loading and statics. For example, if you want a DocumentBuilderFactory, you call the static factory method DocumentBuilderFactory.newInstance(). Behind that façade, the newInstance methods tries every class loader trick in the book (and some that aren’t) to create an instance of an implementation subclass of the DocumentBuilderFactory class. Trying to influence what implementation is used is non-trivial (services model, properties, conventions in class name), and usually global for the VM. Also it is a passive model. The implementation code can not do anything to advertise its availability, nor can the user list the possible implementations and pick the most suitable implementation. It is also not dynamic. Once an implementation hands out an instance, it can not withdraw that object. Worst of all, the factory mechanism is a convention used in hundreds of places in the VM where each factory has its own unique API and configuration mechanisms. There is no centralized overview of the implementations to which your code is bound.

    The solution to all these issues is the OSGi service registry. A bundle can create an object and register it with the OSGi service registry under one or more interfaces. Other bundles can go to the registry and list all objects that are registered under a specific interfaces or class. For example, a bundle provides an implementation of the DocumentBuilder. When it gets started, it creates an instance of its DocumentBuilderFactoryImpl class and registers it with the registry under the DocumentBuilderFactory class. A bundle that needs a DocumentBuilderFactory can go to the registry and ask for all available services that extend the DocumentBuilderFactory class. Even better, a bundle can wait for a specific service to appear and then get a call back.

    A bundle can therefore register a service, it can get a service, and it can listen for a service to appear or disappear. Any number of bundles can register the same service type, and any number of bundles can get the same service. This is depicted in the following figure.

    services

    What happens when multiple bundles register objects under the same interface or class? How can these be distinguished? The answer is properties. Each service registration has a set of standard and custom properties. A 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 that 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 that they no longer use the service object and drop any references. We know, this sounds like a significant complexity but it turns out that helper classes like the Service Tracker and frameworks like iPOJO, Spring, and Declarative Services can make the pain minimal while the advantages are quite large. The service dynamics were added so we could install and uninstall bundles on the fly while the other bundles could adapt. That is, a bundle could still provide functionality even if the http service went away. However, we found out over time that the real world is dynamic and many problems are a lot easier to model with dynamic services than static factories. For example, a Device service could represent a device on the local network. If the device goes away, the service representing it is unregistered. This way, the availability of the service models the availability of a real world entity. This works out very well in, for example, the distributed OSGi model where a service can be withdrawn if the connection to the remote machine is gone. It also turns out that the dynamics solve the initialization problem. OSGi applications do not require a specific start ordering in their bundles.

    The effect of the service registry has been that many specialized APIs can be much modeled with the service registry. Not only does this simplify the overall application, it also means that standard tools can be used to debug and see how the system is wired up.

    Though the service registry accepts any object as a service, the best way to achieve reuse is to register these objects under (standard) interfaces to decouple the implementer from the client code. This is the reason the OSGi Alliance publishes the Compendium specifications. These specification define a large number of standard services, from a Log Service to a Measurement and State specification. All these standardized services are described in great detail.

    SCR Annotations

    The maven-scr-plugin uses the SCR annotations from the corresponding subproject at Apache Felix. All annotations are in the org.apache.felix.scr.annotations package. If you want to use the annotations in your project, you have to use a maven-scr-plugin version >= 1.24.0 and make sure that you add a dependency to the annotations to your POM:

    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.scr.annotations</artifactId>
        <version>1.12.0</version>
    </dependency>
    

    The following annotations are supported:

    • @Component
    • @Activate, @Deactivate, and @Modified
    • @Service
    • @Property
    • @Reference

    The annotations itself do not support the new features from R6 or above. It is suggested to use the official OSGi annotations for Declarative Services instead.

    @Component

    The @Component annotation is the only required annotation. If this annotation is not declared for a Java class, the class is not declared as a 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.

    Supported attributes:


    ds
    Defaulttrue
    SCR Descriptor: —
    Metatype Descriptor: —
    Whether Declarative Services descriptor is generated or not. If this parameter is not set or set to true the Declarative Services descriptor is generated in the service descriptor file for this component. Otherwise no Declarative Services descriptor is generated for this component.


    specVersion
    Default1.0
    SCR Descriptor: —
    Metatype Descriptor: —
    Defines what Declarative Services specification the component is written against. Though the Maven SCR Plugin is very good at detecting whether components are written against the original or a newer specification, there are some cases, where the plugin may fail. For these cases, the specVersion attribute may be set to the correct version. Currently supported values for this attribute are 1.0 and 1.1. Since version 1.4.1 of the Maven SCR Plugin and version 1.0.1 of the SCR Annotations.


    metatype
    Defaultfalse
    SCR Descriptor: —
    Metatype Descriptor: —
    Whether Metatype Service data is generated or not. If this parameter is set to true Metatype Service data is generated in the metatype.xml file for this component. Otherwise no Metatype Service data is generated for this component.


    componentAbstract
    Default: see description
    SCR Descriptor: —
    Metatype Descriptor: —
    This marks an abstract service description which is not added to the descriptor but intended for reuse through inheritance. This attribute defaults to true for abstract classes and false for concrete classes.


    inherit
    Defaulttrue
    SCR Descriptor: —
    Metatype Descriptor: —
    Whether any service, property and reference declarations from base classes should be inherited by this class.


    createPid
    Defaulttrue
    SCR Descriptorservice.pid
    Metatype Descriptor: —
    Generate the service.pid property if non is declared.


    name
    Default: Fully qualified name of the Java class
    SCR Descriptorcomponent.name
    Metatype DescriptorOCD.id
    Defines the Component name also used as the PID for the Configuration Admin Service


    enabled
    Defaulttrue
    SCR Descriptorcomponent.enabled
    Metatype Descriptor: —
    Whether the component is enabled when the bundle starts


    factory
    Default: —
    SCR Descriptorcomponent.factory
    Metatype Descriptor: —
    Whether the component is a factory component


    immediate
    Default: —
    SCR Descriptorcomponent.immediate
    Metatype Descriptor: —
    Whether the component is immediately activated


    policy
    DefaultOPTIONAL
    SCR Descriptorcomponent.policy
    Metatype Descriptor: —
    The configuration policy for this component: OPTIONALIGNORE, or REQUIRE. This attribute is supported since version 1.4.0 of the plugin and requires a Declarative Service implementation 1.1 or higher.


    label
    Default%<name>.name
    SCR Descriptor: —
    Metatype DescriptorOCD.name
    This is generally used as a title for the object described by the meta type. This name may be localized by prepending a % sign to the name.


    description
    Default%<name>.name
    SCR Descriptor: —
    Metatype DescriptorOCD.description
    This is generally used as a description for the object described by the meta type. This name may be localized by prepending a % sign to the name.


    configurationFactory
    Defaultfalse
    SCR Descriptor: —
    Metatype DescriptorDesignate.factoryPid
    Is this a configuration factory? (since 1.4.0)

    Abstract Service Descriptions

    If the @Component annotations contains the attribute componentAbstract with a value of true, the containing class is regarded as an abstract class. It is not added to the service descriptor and the tags are not validated. The information about this class is added to the bundle. Classes from other bundles (or the same) can extends this abstract class and do not need to specify the references of the abstract class if they set the inheritparameter on the scr.component tag to true.

    This allows to create abstract classes which already provide some valuable functionality without having to deal with the details like reference definitions in each and every subclass.

    @Activate, @Deactivate, and @Modified

    The Declarative Service version 1.1 allows to specify the name for the activate, deactivate and modified method (see the spec for more information). The @Activate@Deactivate, and @Modified annotation can be used to mark a method to be used for the specified purpose. However, as the DS specifies a method search algorithm, there are rare cases where the marked method is not used (if there is another method with the same name, but a different signature this might happen).

    These annoations have no attribues.

    @Service

    The @Service annotation defines whether and which service interfaces are provided by the component. This is a class annotation.

    This annotation is used to declare <service> and <provide> elements of the component declaration. See section 112.4.6, Service Elements, in the OSGi Service Platform Service Compendium Specification for more information.

    Supported attributes:


    value
    Default: All implemented interfaces
    SCR Descriptorprovide.interface
    The name of the service interface provided by the component. This can either be the fully qualified name or just the interface class name if the interface is either in the same package or is imported. If this property is not set provide elements will be generated for all interfaces generated by the class


    serviceFactory
    Defaultfalse
    SCR Descriptorservice.servicefactory
    Whether the component is registered as a ServiceFactory or not

    Omitting the Service annotation will just define (and activate if required) the component but not register it as a service. Multiple Service annotations may be declared each with its own value. These annotations need to be wrapped into a Services anotation. The component is registered as a ServiceFactory if at least on Service annotations declares the serviceFactory attribute as true.

    @Property

    The @Property annotation defines properties which are made available to the component through the ComponentContext.getProperties() method. These tags are not strictly required but may be used by components to defined initial configuration. Additionally properties may be set here to identify the component if it is registered as a service, for example the service.description and service.vendor properties.

    This annotation can be applied on the component class level or on a field defining a constant with the name of the property.

    This annotation is used to declare <property> elements of the component declaration. See section 112.4.5, Properties and Property Elements, in the OSGi Service Platform Service Compendium Specification for more information.

    Supported attributes:


    name
    Default: The name of constant
    SCR Descriptorproperty.name
    Metatype DescriptorAD.id
    The name of the property. If this tag is defined on a field with an initialization expression, the value of that expression is used as the name if the field is of type String.


    value
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The string value of the property. This can either be a single value or an array.


    longValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The long value of the property. This can either be a single value or an array.


    doubleValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The double value of the property. This can either be a single value or an array.


    floatValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The float value of the property. This can either be a single value or an array.


    intValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The int value of the property. This can either be a single value or an array.


    byteValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The byte value of the property. This can either be a single value or an array.


    charValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The char value of the property. This can either be a single value or an array.


    boolValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The boolean value of the property. This can either be a single value or an array.


    shortValue
    Default: —
    SCR Descriptorproperty.value
    Metatype DescriptorAD.default
    The short value of the property. This can either be a single value or an array.


    label
    Default%<name>.name
    SCR Descriptor: —
    Metatype DescriptorAD.name
    The label to display in a form to configure this property. This name may be localized by prepending a % sign to the name.


    description
    Default%<name>.description
    SCR Descriptor: —
    Metatype DescriptorAD.description
    A descriptive text to provide the client in a form to configure this property. This name may be localized by prepending a % sign to the name.


    propertyPrivate
    Default: Depending on the name
    SCR Descriptor: —
    Metatype Descriptor: See description Boolean flag defining whether a metatype descriptor entry should be generated for this property or not. By default a metatype descriptor entry, i.e. an AD element, is generated except for the properties service.pidservice.descriptionservice.idservice.rankingservice.vendorservice.bundlelocation and service.factoryPid. If a property should not be available for display in a configuration user interface, this parameter should be set to true.


    cardinality
    Default: Depends on property value(s)
    SCR Descriptor: —
    Metatype DescriptorAD.cardinality
    Defines the cardinality of the property and its collection type. If the cardinality is negative, the property is expected to be stored in a java.util.Vector (primitive types such as boolean are boxed in the Wrapper class), if the cardinality is positive, the property is stored in an array (primitve types are unboxed, that is Boolean type values are stored in boolean\[\]()). The actual value defines the maximum number of elements in the vector or array, where Integer.MIN*INT describes an unbounded Vector and Integer.MAX*INT describes an unbounded array. If the cardinality is zero, the property is a scalar value. If the defined value of the property is set in the value attribute, the cardinality defaults to 0 (zero for scalar value). If the property is defined in one or more properties starting with values, the cardinality defaults to Integer.MAX_INT, that is an unbounded array.


    options
    Default: —
    SCR Descriptor: —
    Metatype DescriptorSee below
    See below for a description of the options attribute.

    Generating <properties> elements referring to bundle entries is not currently supported.

    Multiple property annotations on the class level can be embedded in the @Properties annotation. For example:

    @Properties({
        @Property(name = "prop1", value = "value1"),
        @Property(name = "prop2", value = "value2")
    })
    

    Naming the Property

    It is important to carefully define the name of properties. By using a constant of the form

    @Property(value="default value")
    static final String CONSTANT_NAME = "property.name";
    

    and defining the @Property annotation on this constant, the name of the property is taken from the constant value. Thus it may easily be ensured, that both the property in the descriptor files and the property used by the implementation are actually the same. In addition the value attribute can refer to another constant.

    The options Attribute

    Some properties may only be set to a set of possible values. To support user interfaces which provide a selection list of values or a list of checkboxes the option values and labels may be defined as parameters to the @Property annotation.

    The value of the options attribute is a list of @PropertyOptions annotations:

    @Property(name = "sample",
        options = {
            @PropertyOption(name = "option1", value = "&option.label.1"),
            @PropertyOption(name = "option2", value = "&option.label.2")
        }
    )
    

    The @PropertyOption‘s name is used as the value while the parameter value is used as the label in the user interface. This label may be prepended with a % sign to localize the string.

    The options are written to the metatype.xml file as Option elements inside the AD element defining the property. The name of the parameter will be used for the Option.value attribute while the value of the parameter defines the Option.label attribute.

    Multivalue Properties

    Generally the value of a property is scalar, that is a property has a single value such as true5 or "This is a String". Such scalar values are defined with the different value attributes of the Property annotation. In the case of a scalar property value, the cardinality parameter value is assumed to be 0 (zero) unless of course set otherwise.

    There may be properties, which have a list of values, such as a list of possible URL mappings for an URL Mapper. Such multiple values are defined just by comma separate as the value of the annotation parameter.

    If the cardinality of the property is not explicilty set with the cardinality property, it defaults to Integer.MAX_INT, i.e. unbound array, if multiple values are defined. Otherwise the cardinality parameter may be set for example to a negative value to store the values in a java.util.Vector instead.

    @Reference

    The @Reference annotation defines references to other services made available to the component by the Service Component Runtime.

    This annotation may be declared on a Class level or any Java field to which it might apply. Depending on where the annotation is declared, the parameters may have different default values.

    This annotation is used to declare <reference> elements of the component declaration. See section 112.4.7, Reference Element, in the OSGi Service Platform Service Compendium Specification for more information.

    Supported parameters:


    name
    Default: Name of the field
    SCR Descriptorreference.name
    The local name of the reference. If the Reference annotation is declared in the class comment, this parameter is required. If the annotation is declared on a field, the default value for the name parameter is the name of the field


    interfaceReference
    Default: Type of the field
    SCR Descriptorreference.interface
    The name of the service interface. This name is used by the Service Component Runtime to access the service on behalf of the component. If the Reference annotation is declared on a class level, this parameter is required. If the annoation is declared on a field, the default value for the interfaceReference parameter is the type of the field


    cardinality
    Default1..1
    SCR Descriptorreference.cardinality
    The cardinality of the service reference. This must be one of value from the enumeration ReferenceCardinality


    policy
    Defaultstatic
    SCR Descriptorreference.policy
    The dynamicity policy of the reference. If dynamic the service will be made available to the component as it comes and goes. If static the component will be deactivated and re-activated if the service comes and/or goes away. This must be one of static and dynamic


    target
    Default: —
    SCR Descriptorreference.target
    A service target filter to select specific services to be made available. In order to be able to overwrite the value of this value by a configuration property, this parameter must be declared. If the parameter is not declared, the respective declaration attribute will not be generated


    bind
    Default: See description
    SCR Descriptorreference.bind
    The name of the method to be called when the service is to be bound to the component. The default value is the name created by appending the reference name to the string bind. The method must be declared public or protected and take single argument which is declared with the service interface type


    unbind
    Default: See description
    SCR Descriptorreference.unbind
    The name of the method to be called when the service is to be unbound from the component. The default value is the name created by appending the reference name to the string unbind. The method must be declared public or protected and take single argument which is declared with the service interface type


    strategy
    Defaultevent
    SCR Descriptorreference.strategy
    The strategy used for this reference, one of event or lookup. If the reference is defined on a field with a strategy of event and there is no bind or unbind method, the plugin will create the necessary methods

Run Modes AEM6.3

https://www.aempedia.com/aem6-5/sites/runmodes.html

Run modes allow you to tune your AEM instance for a specific purpose; for example author or publish, test, development, intranet or others.

Installation Run Modes

Installation (or fixed) run modes are used at installation time and then fixed for the entire lifetime of the instance, they cannot be changed.

Installation run modes are provided out-of-the-box:

  • author
  • publish
  • samplecontent
  • nosamplecontent

These are two pairs of mutually exclusive run modes; for example, you can:

  • define either author or publish, not both at the same time
  • combine author with either samplecontent or nosamplecontent (but not both)

Using samplecontent and nosamplecontent

These modes allow you to control the use of sample content. The sample content is defined before the quickstart is built and can include packages, configurations, etc:

  • The samplecontent run mode will install this content (the default mode).
  • The nosamplecontent mode will not install the sample content.

The nosamplecontent run mode is designed for production installations.

Defining configuration properties for a run mode

A collection of values for configuration properties, used for a particular run mode, can be saved in the repository.

The run mode is indicated by a suffix on the folder name. This allows you to store all configurations in one repository as. For example:

  • config
    Applicable for all run modes
  • config.author
    Used for author run mode
  • config.publish
    Used for publish run mode
  • config.<run-mode>
    Used for the applicable run mode; for example, config

Defining additional bundles to be installed for a run mode

Additional bundles that should be installed for a particular run mode can also be specified. For these definitions, install folders are used to hold the bundles. Again the run mode is indicated by a prefix:

  • install.author
  • install.publish

These folders are of type nt:folder and should contain the appropriate bundle.

Starting CQ with a specific run mode

If you have defined configurations for multiple run modes then you need to define which is to be used upon startup. There are several methods for specifying which run mode to use; the order of resolution is:

  1. sling.properties file
  2. -r option
  3. system properties (-D)
  4. Filename detection

When you are using an application server you can also define the run mode in web.xml.

Using the sling.properties file

The sling.properties file can be used to define the required run mode:

  1. Edit the configuration file:
    <cq-installation-dir>/crx-quickstart/conf/sling.properties
  2. Add the following properties; the following example is for author:
    sling.run.modes=author

Using the -r option

A custom run mode can be activated by using the -r option when launching the quickstart. For example, use the following command to launch a AEM instance with run mode set to dev.

java -jar cq-56-p4545.jar -r dev

Using a system property in the start script

A system property in the start script can be used to specify the run mode.

  • For example use the following to launch an instance as a production publish instance located in the US:
    -Dsling.run.modes=publish,prod,us

Filename detection – renaming the jar file

The following two installation run modes can be activated by renaming the installation jar file before installation:

  • publish
  • author

The jar file must use the naming convention:

cq5-<run-mode>-p<port-number>

For example, set the publish run mode by naming the jar file:

cq5-publish-p4503

Defining the run mode in web.xml (with Application Server)

When you are using an application server you can also configure the property:

sling.run.modes

in the file:

WEB-INF/web.xml

This is in the AEM war file and should be updated before deployment.

Logging AEM 6.3

Global Logging

Apache Sling Logging Configuration is used to configure the root logger. This defines the global settings for logging in AEM:

  • the logging level
  • the location of the central log file
  • the number of versions to be kept
  • version rotation; either maximum size or a time interval
  • the format to be used when writing the log messages

Loggers and Writers for Individual Services

In addition to the global logging settings, AEM allows you to configure specific settings for an individual service:

  • the specific logging level
  • the location of the individual log file
  • the number of versions to be kept
  • version rotation; either maximum size or the time interval
  • the format to be used when writing the log messages
  • the logger (the OSGi service supplying the log messages)

AEM uses the following to write log messages to file:

  1. An OSGi service (logger) writes a log message.
  2. Logging Logger takes this message and formats it according to your specification.
  3. Logging Writer writes all these messages to the physical file that you have defined.

Create a Custom Log File

In certain circumstances you may want to create a custom log file with a different log level. You can do this in the repository by:

  • If not already existing, create a new configuration folder (sling:Folder) for your project /apps/<project-name>/config.

  • Under /apps/<project-name>/config, create a node for the new Apache Sling Logging Logger Configuration:

    • Name: org.apache.sling.commons.log.LogManager.factory.config-<identifier> (as this is a Logger)
      Where <identifier> is replaced by free text that you (must) enter to identify the instance (you cannot omit this information). For example, org.apache.sling.commons.log.LogManager.factory.config-MINE
    • Type: sling:OsgiConfig

    Set the following properties on this node:

    • Name: org.apache.sling.commons.log.file
      Type: String
      Value: specify the Log File; for example, logs/myLogFile.log
    • Name: org.apache.sling.commons.log.names
      Type: String[] (String + Multi)
      Value: specify the OSGi services for which the Logger is to log messages; for example, all of the following:

      • org.apache.sling
      • org.apache.felix
      • com.day
    • Name: org.apache.sling.commons.log.level
      Type: String
      Value: specify the log level required (debuginfowarn or error); for example debug
    • Configure the other parameters as required:
      • Name: org.apache.sling.commons.log.pattern
        Type: String
        Value: specify the pattern of the log message as required; for example,
        {0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}

    This step is only necessary when a new Writer is required (i.e. with a configuration that is different to the default Writer).

    Under /apps/<project-name>/config, create a node for the new Apache Sling Logging Writer Configuration:

    • Name: org.apache.sling.commons.log.LogManager.factory.writer-<identifier> (as this is a Writer)
      As with the Logger, <identifier> is replaced by free text that you (must) enter to identify the instance (you cannot omit this information). For example, org.apache.sling.commons.log.LogManager.factory.writer-MINE
    • Type: sling:OsgiConfig

    Set the following properties on this node:

    • Name: org.apache.sling.commons.log.file
      Type: String 
      Value: specify the Log File so that it matches the file specified in the Logger;
      for this example, ../logs/myLogFile.log.
    • Configure the other parameters as required:
      • Name: org.apache.sling.commons.log.file.number
        Type: Long
        Value: specify the number of log files you want kept; for example, 5
      • Name: org.apache.sling.commons.log.file.size
        Type: String
        Value: specify as required to control file rotation by size/date; for example, ‘.’yyyy-MM-dd
  • Read your new log file with your chosen tool.

    The log file created by this example will be ../crx-quickstart/logs/myLogFile.log.

  •  The Felix Console also provides information about Sling Log Support at ../system/console/slinglog; for example http://localhost:4502/system/console/slinglog.

     

    Apache Sling Logging Configuration

    Configure:

    • Log Level and Log File, to define the location and log level of the central logging configuration (error.log). The level can be set to one of DEBUGINFOWARNERROR and FATAL.
    • Number of Log Files and Log File Threshold to define the size and version rotation of the log file.
    • Message Pattern defines the format of the log messages.

    For further information see AEM Logging and Sling Logging.

    Apache Sling Logging Logger Configuration (Factory Configuration)

    Configure:

    • Log LevelLog File and Message Format to define details of the log file and messages.
    • Logger to define the category; for example, only log for com.day.cq.
    • By using Factory Configurations, any number of additional configurations can be added to cater with the various log levels and categories needed.
    • Such configurations are helpful during development; for example, to log TRACE messages for a specific service in a specific log file.
    • Such configurations are helpful in a production environment; for example, to have messages about a specific service logged to an individual log file for easier monitoring.

    For further information see AEM Logging and Sling Logging.

    Apache Sling Logging Writer Configuration (Factory Configuration)

    Configure:

    • Log File to define the existence of a log file.
    • Number of Log Files to define the version rotation.
    • The writer can be used by a Apache Sling Logging Logger Configuration configuration.
    • Such configurations are helpful during development; for example, to log TRACE messages for a specific service in a specific log file.
    • Such configurations are helpful in a production environment; for example, to have messages about a specific service logged to an individual log file for easier monitoring.

    Logging in AEM is based on Sling principles

    \crx-quickstart\logs

    access.log : All access requests to CQ WCM and the repository are registered here.

    error.log : Error messages (of varying levels of severity) are registered here.

    request.log : Each access request is registered here together with the response.

    server.log : All actions made by the server are registered here.

    stderr.log : Holds error messages, again of varying levels of severity, generated during startup.

    stdout.log : Holds logging messages indicating events during startup.