OSGI Configuration: comprehensively explained in AEM

Satyam Gupta
9 min readAug 8, 2024

--

Hello, programmers Best wishes from this blog The main goal of this blog is to present the OSGI in AEM to you, along with details on its configuration, implementations, run mode, and appropriate explanation supported by pertinent examples.

Table of Contents: —

  • OSGi (Open Services Gateway initiative)
  • The OSGi has a layered model
  • Managing OSGi Configurations
  • Key Concepts of OSGi in AEM
  • Annotations used in OSGI
  • Custom OSGI Configuration
  • New OSGI Configuration Pattern
  • Run mode Configurations
  • Types of OSGI Configuration value

OSGi (Open Services Gateway initiative): —

OSGI plays a crucial role in Adobe Experience Manager (AEM) by providing a dynamic module system for Java.

→ It is a fundamental layer in the AEM stack, which is used to control the composite bundle of AEM and the configuration. An OSGi application is a collection of bundles, that interact using service interfaces

→ OSGi supports modular deployment of bundles, controlling the configuration of AEM’s composite bundles, and creating applications from smaller, reusable, and collaborative components.

→ The OSGi specification describes a service platform for the Java programming language that implements a complete and dynamic component model, which does not exist in standalone Java/VM environments.

→It enables AEM to be highly modular, with components that can be installed, updated, and removed dynamically without restarting the entire application. This modularity enhances the maintainability and scalability of AEM applications.

→ Application life cycle management is implemented via APIs that allow for remote downloading of management policies.

→ The service registry allows bundles to detect the addition of new services, or the removal of services, and adapt accordingly.

The OSGi has a layered model: —

  • Bundles — Bundles are normal jar components with extra manifest headers.
  • Services — The service layer, which holds the service side of the framework, keeps the service registry and manages it.
  • Life-Cycle — The lifecycle layer manages and keeps track of the frameworks and bundle's lifecycle state. It is used to install or uninstall framework objects and start or stop them.
  • Modules — The module layer, which is the bundle space, holds the bundles installed on the framework and is managed through the lifecycle layer.
  • Security — The security layer, which extends the Java 2 security architecture, is optional. It validates the bundle signatures and controls the component access rights when active.
  • Execution Environment — The execution environment layer, which is the bottom layer on which the bundles live, is selected to fit the underlying hardware or operating system.

Managing OSGi Configurations: —

In AEM, you can manage OSGi configurations through:

  1. Felix Web Console: Accessible at /system/console/configMgr, where you can view and manage all OSGi configurations.
  2. OSGi Configuration Files: These files are typically stored under /apps/<project>/config or /conf/<project>/settings.
  3. Sling Configuration Management: Allows you to manage configurations via OSGi Config Factory and Apache Sling Context-Aware Configuration.

Key Concepts of OSGi in AEM: —

Bundles:

→Bundles are the primary unit of modularization in OSGi. They are essentially JAR files with additional metadata.

→ Each bundle has its lifecycle and can be independently started, stopped, updated, or uninstalled.
The bundle life cycle states are as follows.

  • INSTALLED: The bundle has been successfully installed. The framework knows enough about this bundle to attempt to load it.
  • RESOLVED: All resources needed for this bundle have been loaded successfully and the bundle is ready to be started. This is also the state the bundle would be in, once successfully stopped.
  • STARTING: The bundle is being started, but has not finished starting.
  • ACTIVE: The bundle has been successfully activated and is running, ready to be used.
  • STOPPING: The bundle is being stopped but has not finished stopping.
  • UNINSTALLED: The bundle has been uninstalled. Once uninstalled, nothing can be done with the module.

Components:

  • OSGi components are defined using Java classes, managed by the OSGi framework, and are capable of providing services to other components and bundles within the AEM environment.
  • Components can register themselves as services to be used by other components.

Services:

  • Services are objects that are registered in the OSGi service registry. They can be shared and reused by different bundles.
  • Services are typically interfaces that are implemented by components.
  • OSGi services allow different parts of the application to interact and share functionality in a loosely coupled manner.

Configurations:

  • OSGi configurations allow you to externalize the configuration parameters of components.
  • In AEM, configurations can be managed through the OSGi Web Console, Apache Sling Configuration, or directly via the CRX repository.

Before continuing to an example I want to discuss R6 annotation which is used in OSGI.

R6 annotation allows us to add configurations to OSGI Services with the help of @Designate annotation. @Designate is a must to have ocd(object class definition) property to declare the service name as mentioned in the below syntax.

@Designate(ocd = StudentConfiguration.class)

Annotations used in OSGI: —

@interface

@interface annotation is used to define configuration interfaces for OSGi components. These interfaces allow you to manage and externalize configuration parameters for your components.

The @interface annotation is part of Java's annotation mechanism and is used to define custom annotations. When used in the context of OSGi in AEM, it is typically combined with OSGi annotations such as @ObjectClassDefinition and @AttributeDefinition to define configuration interfaces.

@component

@Component defines the class as an OSGi component and registers it as a service.

We can create an OSGI service with the help of @Component annotation from org.osgi.service.component.annotations package and register it as an OSGI service.

@Designate

@Designate annotation is used to associate a configuration interface with an OSGi component.
This allows you to define and manage configurations externally and inject them into your components.

→ Associates the configuration interface with the component. The ocd attribute points to the configuration interface class.

@ObjectClassDefinition

@ObjectClassDefinition is an annotation provided by OSGi to define metadata for OSGi configuration classes. This annotation is used to create a configuration interface that allows you to manage and externalize configuration parameters for your OSGi components.

@AttributeDefinition

Defines individual configuration properties, including their names, descriptions, and default values.

Services can be consume using ‘@Reference’ annotation in Servlet and other services. Use ‘@OSGiService’ annotation to inject service in sling model.

Custom OSGI Configuration: —

Let’s examine OSGI Configuration, how it is implemented using an example, and what the necessary annotation is.

In this example, we are going to create a custom OSGI Configuration named StudentConfiguration.

Step 1
Create a configuration interface with the help of @interface annotation will represent the fields in our configuration. and provide @ObjectClassDefinition annotation on top of the class.

StudentConfiguration.java

package com.adobe.aem.guides.wknd.core.service;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.osgi.service.metatype.annotations.Option;

@ObjectClassDefinition(name = "Student Details", description = "Enter your Students details here" )
public @interface StudentConfiguration {

@AttributeDefinition(name = "Student Name", type = AttributeType.STRING,
description = "Enter Student Name here")
public String getStudentName() default "Satyam";

@AttributeDefinition(name = "Roll Number", type = AttributeType.INTEGER,
description = "Enter Roll Number here")
public int getRollNumber() default 3;

@AttributeDefinition(name = "Regular", type = AttributeType.BOOLEAN,
description = "Is student is regular")
public boolean getRegular() default true;

@AttributeDefinition(name = "Subjects", type = AttributeType.STRING,
description = "See Your Subjects")
public String[] getSubjects() default {"maths,english,sanskrit"};

@AttributeDefinition(name = "Countries", type = AttributeType.STRING,
description = "Select your Countries",
options = {
@Option(label = "India", value = "india"),
@Option(label = "Russia", value = "russia"),
@Option(label = "France", value = "france"),
@Option(label = "America", value = "america")
})
public String getCountries() default "India";
}

In the above code: we have created StudentConfiguration in OSGi where we added metadata and fields for the configuration file.

@AttributeDefinition annotation using name, description, and type of property as shown above.

Step 2 —
Create the below interface named StudentConfigurationMethods.java having getter methods for configuration.

package com.adobe.aem.guides.wknd.core.service;

public interface StudentConfigurationMethods {

String getStudentName();
int getRollNumber();
String[] getSubjects();
String getCountries();
boolean getregular();


}

Step 3: —
Create the below class StudentConfigurationMethodsImpl.java which implements the StudentConfigurationMethods.java interface and implements all getter methods.

package com.adobe.aem.guides.wknd.core.service.impl;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.Designate;

import com.adobe.aem.guides.wknd.core.service.StudentConfiguration;
import com.adobe.aem.guides.wknd.core.service.StudentConfigurationMethods;

@Component(service = StudentConfigurationMethods.class)
@Designate(ocd = StudentConfiguration.class)
public class StudentConfigurationMethodsImpl implements StudentConfigurationMethods{


private String studentName;
private int rollNumber;
private boolean regular;
private String[] subjects;
private String countries;

@Activate()
protected void start(StudentConfiguration config){
studentName = config.getStudentName();
rollNumber = config.getRollNumber();
regular = config.getRegular();
subjects = config.getSubjects();
countries = config.getCountries();
}

@Override
public String getStudentName() {
return studentName;
}

@Override
public int getRollNumber() {
return rollNumber;
}

@Override
public String[] getSubjects() {
return subjects;
}

@Override
public String getCountries() {
return countries;
}

@Override
public boolean getregular() {
return regular;
}

}

In the above code:

  • Define the Configuration Interface: Use @ObjectClassDefinition and @AttributeDefinition.
  • Implement the OSGi Component: Use @Designate to link the configuration interface and handle the configuration in activate and modified methods.
  • Manage the Configuration: Through the Felix Web Console or configuration files.

Now go to Apache Felix Console and check this configuration
go to this URL: http://localhost:4502/system/console/configMgr and search StudentConfiguration.

now see the result:

New OSGI Configuration Pattern: —

As part of the latest OSGI configuration, we use .cfg.json as a file extension and content in JSON format as as shown below.

Step 4— Now create a JSON file for the default values of our configuration. Create “com.wknd.core.services.impl.CoveoProductsStudentConfigurationMethodsImpl.cfg.json” under.“\aem\ui.config\src\main\content\jcr_root\apps\demoproject\osgiconfig\config\”

{
"getStudentName": "Satyam",
"getRollNumber": 1020,
"getSubjects": ["Java","C++"],
"getCountries": "India",
"getRegular": true
}

Now you are ready to work on OSGI in AEM.

Run mode Configurations: —

Run mode allows us to declare environment-specific properties and values. AEM Run modes also allow us to configure an AEM instance depending on requirements and load environment-specific configurations.

For example, we are connecting with a third-party API to log in end users in Production. However, we will require this third-party API to test functionalities in lower environments (DEV, QA, UAT, and Stage). Run mode helps us load environment-specific URLs and configurations.

AEM as a Cloud Service does not allow using run modes to install content for specific environments or services. If a development environment must be seeded with data or HTML that is not in the staging or production environments, Package Manager can be used.

AEM as a Cloud Service Runmodes are well defined based on the environment type and service. The supported run mode configurations are config, config.author, config.author.dev, config.author.rde, config.author.stage, config.author.prod, config.publish, config.publish.dev, config.publish.rde, config.publish.stage, config.publish.prod, config.dev, config.rde, config.stage, config.publish.prod, config.dev, config.rde, config.stage, config.prod,

The OSGI configuration that has the most matching run modes is used.

When developing locally, a run mode startup parameter, -r, is used to specify the run mode OSGI configuration.

Java -jar aem-sdk-quickstart-xxxx.x.xxx.xxxx-xxxx.jar -r publish,dev

Types of OSGI Configuration value: —

There are three varieties of OSGi configuration values that can be used with Adobe Experience Manager as a Cloud Service.

  1. Inline values, Hard-coded OSGi configuration which is stored/pushed through Git. For example:
{    
"connection.timeout": 1000
}

2. Secret values, Must not be stored in Git for security reasons. These variables we create in the cloud manager. For example:

{ 
"password": "$[secret:password]"
}

3. Environment-specific values, which are values that vary between Development environments, and thus cannot be accurately targeted by run mode (since there is a single dev run mode in Adobe Experience Manager as a Cloud Service). For example:

{  
"username": "$[env:username]"
}

A single OSGi configuration file can use any combination of these configuration value types in conjunction. For example:

{ 
"connection.timeout": 1000,
"password": "$[secret:password]",
"username": "$[env:username]"
}

Note: As of today, up to 200 variables per environment can be declared.

This is all related to OSGI in AEM where we have discussed OSGI Configuration, Run Mode, Variable, and Implementation with examples.

Now you can understand all about the OSGI in AEM.

I hope you found this article interesting and informative. Please share it with your friends to spread the knowledge.

You can follow me for upcoming blogs follow.

--

--

Satyam Gupta
Satyam Gupta

Written by Satyam Gupta

AEM Full Stack Developer | Adobe Analytics Developer | Java

No responses yet