Components

Overview

The introduction of the HTL templating language has eliminated the need for custom JSP tags, scriptlets, and other unpleasantries when separating a component’s view from it’s supporting business logic. The Sling Models framework offers a robust, POJO-based development pattern that the AEM Library augments to greatly simplify AEM component development.

Abstract Component Class

Model classes may extend the com.icfolson.aem.library.core.components.AbstractComponent class to expose numerous convenience methods for retrieving/transforming property values, traversing the content repository, and generally reducing the amount of boilerplate code needed to perform common node- and property-based operations for a component.

The Java/Groovy model class for the component should expose getters for the values that required to render the component’s view.

import com.icfolson.aem.library.core.components.AbstractComponent
import com.icfolson.aem.library.api.content.page.PageDecorator
import org.apache.sling.models.annotations.Model

@Model(adaptables = [Resource, SlingHttpServletRequest])
class Navigation extends AbstractComponent {

    @Inject
    PageDecorator currentPage

    String getTitle() {
        get("jcr:title", "")
    }

    List<PageDecorator> getPages() {
        currentPage.getChildren(true)
    }
} 

Injectable Component Node

Alternatively, model classes may inject an instance of the com.icfolson.aem.library.api.node.ComponentNode class to provide the same functionality as the abstract class described above.

import com.icfolson.aem.library.api.node.ComponentNode

@Model(adaptables = [Resource, SlingHttpServletRequest])
class Navigation {

    @Inject
    ComponentNode componentNode

    String getTitle() {
        componentNode.get("jcr:title", "")
    }
}

See the ComponentNode Javadoc for details of the available methods.

Sling Models Injectors

In addition to the AEM Library’s component API, the library also supplies a set of custom Sling Models injectors to support injection of common Sling and AEM objects for the current component. See the Injectors page for additional information.

HTL Integration

Sling Models-based components (i.e. POJOs with the @org.apache.sling.models.annotations.Model annotation) can be instantiated in HTL templates with a data-sly-use block statement. Since the AEM Library components are just “decorated” Sling Models, nothing additional is required.

The HTL template for the preceding Navigation component would be implemented as follows:

<sly data-sly-use.navigation="com.projectname.components.content.Navigation">
    <h1>${navigation.title}</h1>

    <ul data-sly-list.page="${navigation.pages}">
        <li><a href="${page.href}">${page.title}</a></li>
    </ul>
</sly>

Component Development Guidelines

  • Component beans should be read-only since requests in publish mode are generally bound to an anonymous user without write access. Repository write operations should be performed only in author mode (and replicated only when a page is activated by a content author). Since component classes are executed in both author and publish modes, ideally one should consider alternative approaches to performing write operations in a component bean:
    • Delegate write operations to an OSGi service containing a service-appropriate Sling Resource Resolver.
    • Refactor the component to perform dialog-based content modifications by attaching a listener to a dialog event.
    • Register a JCR event listener to trigger event-based repository updates.
  • Classes should remain stateless and contain no setter methods. Since the lifecycle of a component/model is bound to a request, state should be maintained client-side using cookies, local storage, or HTML data attributes.

Back to top