New Configuration Approach for AEM 6

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

Since OSGI R6, developers can improve traditional AEM 6 configurations 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 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 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.

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;
}

Conclusions

The new approach reduces class complexity and improves readability. Configuration interfaces become self-documenting. Type safety eliminates casting errors, default values prevent configuration misses, and configurations become reusable across classes, adhering to DRY principles.

Source code examples available on GitHub.