user7906470
user7906470

Reputation:

How to scale an OSGi Service with Declarative Services correctly?

Project description:

I have a simple demo project with OSGi. The Domain is a weather station which has multiple sensor types. Each sensors sends its data to the weather station. Via an API the data is exposed and visualized on a website via a plot.

Goal:

E.g: I currently have three different sensor types. One for measuring the wind speed, temperature and humidity. The weather station should have multiple wind sensor instances (Cardinality.MULTIPLE).

Status quo:

Currently I am solving this with creation of a WindSpeedSensor and a WindSpeedAdvancedSensor service. I already have implemented a custom command for Apache Karaf where I can send specific configuration commands to my service. So the sensor can be configured to generate measurements in a specific range.

Desired condition:

An optimal solution would be to start additional instances of WindSpeedSensor via Karaf commmand line. The should not be the need of artificial WindSpeedSensors to achieve the goal of multiple services for the WeatherStation class.

Question:

How can I achieve this? I am new to OSGi and declarative services and I am curious how experts in OSGi solve this. Thanks in advance for your time and feedback.

Upvotes: 0

Views: 331

Answers (2)

Pasi Österman
Pasi Österman

Reputation: 2187

I've only used OSGi with Karaf so this might be somewhat different for other environments.

If you need OSGi Service for each configuration file you can setup such service with declarative service annotations for example like this.

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

import com.example.service.config.ExampleServiceConfig;

@Component(
    immediate = true, service = ExampleService.class, 
    configurationPolicy = ConfigurationPolicy.REQUIRE,
    configurationPid = "com.example.service.ExampleService"
)
@Designate(ocd = ExampleServiceConfig.class, factory = true)
public class ExampleService {

    @Activate
    public void onServiceActivate(BundleContext context, ExampleServiceConfig config){
        System.out.println(config.hello_message());
    }
}

Then define type-safe configuration for the service for example like this:

import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@ObjectClassDefinition(name = "ExampleService Configuration")
public @interface ExampleServiceConfig {
 
    String hello_message() default "hello world";
    String osgi_jndi_service_name() default "unique.service.name";
}

Since singleton configurations use file names like <configurationPid>.cfg factory configurations use format <configurationPid>-<InstanceName>.cfg so to create two instances of ExampleService above you can create for example following configurations:

com.example.service.ExampleService-InstanceA.cfg

hello.message=Hello from Instance A
osgi.jdni.service.name=InstanceA

com.example.service.ExampleService-InstanceB.cfg

hello.message=Hello from Instance B
osgi.jdni.service.name=InstanceB

At least in Karaf this will create two instances of ExampleService and two configurations with unique guid of some sort (instead of Instance name). To refer to specific service instance you can use target property from reference annotation.

@Reference(
    target = "(osgi.jdni.service.name=InstanceA)"
)
ExampleService exampleService;

Upvotes: 1

BJ Hargrave
BJ Hargrave

Reputation: 9384

You can use Factory Configurations (see https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-deployment). For each configuration under the factory pid, DS will create a component configuration. This allows one component to be created multiple times based upon factory configurations in Configuration Admin.

Upvotes: 0

Related Questions