New Configuration Approach for AEM 6

Evgeniy Fitsner Software Engineer
4 min read
New Configuration Approach for AEM 6

Introduction

Since OSGi R6, developers can move away from traditional AEM configuration patterns and create cleaner, more maintainable code. Declarative Services 1.3 (DS 1.3) facilitates this modernization within AEM 6 and Java 8 environments.

Prerequisites

  1. Verify DS 1.3 is deployed in your OSGi environment.
  2. Create an Apache Maven project baseline.
  3. Specify the required dependencies:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.scr.annotations</artifactId>
    <version>1.12.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>biz.aQute</groupId>
    <artifactId>bndlib</artifactId>
    <version>1.43.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.osgi</groupId>
    <artifactId>org.osgi.service.component.annotations</artifactId>
    <version>1.3.0</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>biz.aQute.bnd</groupId>
    <artifactId>biz.aQute.bndlib</artifactId>
    <version>3.3.0</version>
    <scope>compile</scope>
</dependency>
  1. Update Maven plugins for Java 8 and DS 1.3 support:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-scr-plugin</artifactId>
                <version>1.23.0</version>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

The Old Configuration Approach

Traditional AEM configurations embedded properties within component classes. Configuration instantiation required manual casting and type conversion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Activate
@Modified
protected void init(ComponentContext componentCtx, BundleContext bundleCtx,
    Map<String, ?> properties) {
    enabled = PropertiesUtil.toBoolean(
        componentCtx.getProperties().get(ENABLE_CACHE), true);
    heap = PropertiesUtil.toLong(
        componentCtx.getProperties().get(CACHE_HEAP), DEFAULT_CACHE_HEAP);
    offHeap = PropertiesUtil.toLong(
        componentCtx.getProperties().get(CACHE_OFFHEAP),
        DEFAULT_CACHE_OFFHEAP);
    initialCitiesProp = PropertiesUtil.toStringArray(
        componentCtx.getProperties().get(INITIAL_CITIES));
    areas = PropertiesUtil.toString(
        componentCtx.getProperties().get(ENABLED_CACHE_AREAS), "1");
}

This approach mixes configuration code with business logic, creating bloated classes that are harder to read and maintain.

The New Configuration Approach

The modernized strategy separates concerns effectively:

  1. Create an interface marked with @ObjectClassDefinition containing all configuration properties with proper type safety and default values.
  2. Annotate the implementation class with @Designate to reference the configuration interface.
  3. Inject configuration via @Activate and @Modified methods:
1
2
3
4
5
6
7
8
private BaseCacheConfig cacheConfig;

@Activate
@Modified
protected void init(ComponentContext componentCtx, BundleContext bundleCtx,
    BaseCacheConfig cacheConfig) {
    this.cacheConfig = cacheConfig;
}

The configuration interface defines properties with annotations like @AttributeDefinition, providing self-documenting code with type-safe defaults.

Benefits

  • Reduced complexity: Configuration is separated from business logic
  • Self-documenting: Configuration interfaces describe their own properties
  • Type safety: Eliminates casting errors at runtime
  • Default values: Prevents configuration misses and null pointer exceptions
  • Reusability: Configuration interfaces can be shared across multiple components
  • DRY principle: No repeated property parsing code across classes

Source code examples are available on GitHub.

Contents