AEM in 40 Days
CalendarPhase 5 · Advanced Development

Day 30 of 40

OSGi Configuration

Run-mode configs, OCD, and handling secrets

~50 min read3 videos4 source pages

By the end of today you should be able to

  1. Define typed OSGi configuration with an Object Class Definition
  2. Ship configuration as files in ui.config using run-mode folders
  3. Explain configuration precedence when several run modes match
  4. Handle secrets correctly on AEM as a Cloud Service

Typed configuration with OCD

An Object Class Definition is an annotation interface describing your component's configuration. It gives you type safety, defaults and labels for the web console in one place:

@ObjectClassDefinition(
    name = "WKND Adventure Service",
    description = "Settings for the adventure lookup service")
public @interface AdventureServiceConfig {

    @AttributeDefinition(name = "API endpoint",
                         description = "Base URL of the adventures API")
    String apiEndpoint() default "https://api.example.com";

    @AttributeDefinition(name = "Timeout (ms)")
    int timeout() default 5000;

    @AttributeDefinition(name = "Enabled")
    boolean enabled() default true;
}

Then designate it on the component and receive it in @Activate:

@Component(service = AdventureService.class)
@Designate(ocd = AdventureServiceConfig.class)
public class AdventureServiceImpl implements AdventureService {

    private String endpoint;

    @Activate
    @Modified
    protected void activate(AdventureServiceConfig config) {
        this.endpoint = config.apiEndpoint();
    }
}
Add @Modified

Without it, changing configuration in the web console deactivates and reactivates the whole component. With @Modified on the same method, the component is updated in place — which matters when activation is expensive or the component holds state.

Shipping configuration as files

Editing configuration in the web console is fine locally but never a deployment mechanism — Cloud Service instances are replaced, and console edits do not survive. Configuration ships as JSON files in ui.config:

ui.config/src/main/content/jcr_root/apps/wknd/osgiconfig/
  config/
    com.adobe.aem.guides.wknd.core.AdventureServiceImpl.cfg.json
  config.author/
  config.publish/
  config.author.dev/
  config.publish.prod/

The filename is the component's PID — usually the fully qualified class name. The content is plain JSON:

{
  "apiEndpoint": "https://api-dev.example.com",
  "timeout": 10000,
  "enabled": true
}

For a factory configuration, append an identifier after a dash: com.example.MyFactory-instance1.cfg.json.

Precedence

When several folders could apply, the most specific run-mode match wins — the one matching the greatest number of active run modes. With author and dev active:

  • config.author.dev — 2 matches, wins
  • config.author — 1 match
  • config.dev — 1 match
  • config — the fallback

Two folders matching equally many run modes is ambiguous and to be avoided — put the shared value in config and override only where it genuinely differs.

Secrets

An API key must never be committed. On Cloud Service the mechanism is Cloud Manager environment variables of type secret, referenced from configuration with the $[secret:...] placeholder:

{
  "apiEndpoint": "$[env:ADVENTURE_API_URL;default=https://api.example.com]",
  "apiKey": "$[secret:ADVENTURE_API_KEY]"
}
  • $[env:NAME] — a plain environment variable, with an optional ;default=.
  • $[secret:NAME] — a secret variable. Write-only in Cloud Manager: settable, never readable back.

Variables are set per environment through the Cloud Manager UI or API, so dev, stage and prod each carry their own values while the configuration file in Git stays identical and safe to read.

The rule

If a value would be damaging in a public repository, it is a secret variable. Never a config file, never a Java constant, never a comment "to be replaced before go-live".

Checking what actually applied

/system/console/configMgr shows the effective configuration for every component. When behaviour differs between environments, this is where you confirm which run-mode folder won and what values landed — far quicker than reasoning about precedence from the file tree.

Today's takeaway

OCD for typed configuration, @Modified to avoid needless restarts, run-mode folders for per-environment values, and $[secret:...] for anything sensitive.

Watch

Adobe's own videos for this topic. They load only when you press play.

OSGi Services - OSGi Configurations - Part 1
OSGi Services - OSGi Configurations - Part 2
OSGI Configs

Read on Experience League

The primary sources these notes are drawn from.

Your notes

Saved automatically to this browser.

Check yourself

10 questions on today's material. 80% to pass.

Take the quiz