Blogs > OSGI Configuration Factory
AEM Sites
OSGI Configuration Factory
| July 24, 2023What is OSGI In AEM ?
OSGi is a fundamental element in the technology stack of Adobe Experience Manager (AEM). It is used to control the composite bundles of AEM and their configuration. OSGi “provides the standardized primitives that allow applications to be constructed from small, reusable, and collaborative components. These components can be composed into an application and deployed”.
What is OSGI Configuration In AEM ?
OSGi Configurations in AEM are used to set up and customize the properties of OSGi components and services. These Configurations are often stored in configuration files or managed through the AEM Web Console.
What is OSGI Factory Configuration In AEM ?
OSGi Factory Configuration in Adobe Experience Manager (AEM) refers to a way of creating multiple instances of an OSGi service, each with its own unique configuration. This is particularly useful when you need several instances of a service with different settings.
Key Concepts of OSGi Factory Configuration:
-
Factory Configuration:
Unlike standard OSGi Configurations, which apply a single configuration to a single service instance, factory Configurations allow multiple instances of a service to be created, each with a unique configuration. Each instance is created with a distinct configuration, enabling different behavior or settings for each instance.
-
Identifiers:
Each factory configuration instance is identified by a unique identifier, typically appended to the configuration’s PID (Persistent Identifier).
-
Configuration Format:
Factory Configurations often use .config or .cfg.json files, with a filename pattern that includes a factory identifier.
Now we will see Implementation of factory configuration
Here is the code to create Osgi Configuration :
-
package com.demo.core.conf; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.AttributeType; import org.osgi.service.metatype.annotations.ObjectClassDefinition; @ObjectClassDefinition(name = "Osgi Factory Configuration", description = "Osgi Factory Configuration Demo") public @interface OsgiFactoryConfiguration { @AttributeDefinition(name = "configId",description = "ConfigId",type = AttributeType.INTEGER) int configurationId(); @AttributeDefinition(name = "configName",description = "ConfigName",type = AttributeType.STRING) String configName() default "Config #"; }
Create a Service which contains the methods to get Configuration Name and Ids. :
-
package com.demo.core.services; import java.util.List; public interface OsgiFactoryConfigService { int getConfigurationId(); String getConfigName(); public OsgiFactoryConfigService get(int configId); List
getAllConfiguration(); }
Create a Java Class with @Component Annotation and Implements the service and override all the Methods. Under @Designate Annotation include the Configuration class, to include the configuration class use "ocd" Interface. ocd is @ObjectClassDefinition Annotation is used to define a class or interface that describes the configuration options available for a particular OSGi service or component. This annotation helps in creating a clear and structured way to handle configuration properties, making them easier to manage and understand.
-
package com.demo.core.services.impl; import com.demo.core.conf.OsgiFactoryConfiguration; import com.demo.core.conf.OsgiFactoryConfigurator; import com.demo.core.services.OsgiFactoryConfigService; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.annotations.*; import org.osgi.service.metatype.annotations.Designate; import java.io.IOException; import java.util.ArrayList; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; @Component(service = OsgiFactoryConfigService.class, configurationPolicy = ConfigurationPolicy.REQUIRE) @Designate(ocd = OsgiFactoryConfiguration.class,factory = true) public class OsgiConfigurationFactoryImpl implements OsgiFactoryConfigService { private int configurationId; private String configurationName; List
list; @Activate @Modified public void activate(final OsgiFactoryConfiguration config) throws IOException { configurationId = config.configurationId(); configurationName = config.configName(); } @Reference(service = OsgiFactoryConfigService.class, cardinality = ReferenceCardinality.MULTIPLE , policy = ReferencePolicy.DYNAMIC) public void bindOSGiFactoryConfig(final OsgiFactoryConfigService configService) { if (list == null) { list = new ArrayList<>(); } list.add(configService); } public void unbindOSGiFactoryConfig(final OsgiFactoryConfigService configService) { list.remove(configService); } @Override public int getConfigurationId() { return configurationId; } @Override public String getConfigName() { return configurationName; } @Override public List getAllConfiguration() { return list; } @Override public OsgiFactoryConfigService get(int configId) { for (OsgiFactoryConfigService confFact : list) { if (configurationId == confFact.getConfigurationId()) return confFact; } return null; } }
Cardinality in AEM ?
Cardinality in OSGi is specified using annotations or XML Configurations and indicates whether a service dependency is mandatory or optional, and whether the component expects a single instance or multiple instances of the service.
Cardinality Options
-
Mandatory Single (1..1)
The component requires exactly one instance of the service. The component cannot function without this service, and only one instance is expected.
-
Optional Single (0..1)
The component can function without the service (optional), but if the service is present, only one instance is expected.
-
Mandatory Multiple (1..n):
The component requires at least one instance of the service but can accept multiple instances. It must have at least one service bound to function properly.
-
Optional Multiple (0..n):
The component can function without the service, but if the service is available, it can bind to multiple instances.
Create a Java Class with @Model as an annotation through which we can get all the Configurations that passed from Felic console
-
package com.demo.core.models.impl; import com.demo.core.models.OsgiConfigurationModel; import com.demo.core.services.OsgiFactoryConfigService; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import java.util.List; @Model(adaptables = SlingHttpServletRequest.class, adapters = OsgiConfigurationModel.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class OsgiConfigurationModelImpl implements OsgiConfigurationModel { @OSGiService OsgiFactoryConfigService osgiFactoryConfigService; @Override public List
getAllConfigurations() { return osgiFactoryConfigService.getAllConfiguration(); } }
Create the components and with the help of Slightly we can display all the Configurations in AEM page.
Now Redirect to localhost:4502/system/console/configMgr and search you configuration name.
After refreshing the Page you will find all the Configurations with the unique identifier.
Click On '+' icon to add the Configurations
Now login in to the AEM , Go to site Console and open the page